diff --git a/common/pom.xml b/common/pom.xml index 920640fd2..313903e28 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -38,7 +38,7 @@ commons-io commons-io - 2.11.0 + 2.12.0 org.bouncycastle diff --git a/common/src/main/java/com/genexus/util/GXFileInfo.java b/common/src/main/java/com/genexus/util/GXFileInfo.java index 7b5e2e2a1..bc2706525 100644 --- a/common/src/main/java/com/genexus/util/GXFileInfo.java +++ b/common/src/main/java/com/genexus/util/GXFileInfo.java @@ -68,7 +68,7 @@ public boolean createNewFile() throws IOException{ return fileSource.createNewFile(); } public boolean createNewFile(InputStream input) throws IOException{ - fromBytes(SpecificImplementation.GXutil.toByteArray(input)); + fromInputStream(input); return true; } public boolean delete(){ @@ -180,6 +180,16 @@ public void fromBytes(byte[] data) throws IOException destination.write(data, 0, data.length); } } + private void fromInputStream(InputStream input) throws IOException + { + try (OutputStream output = new BufferedOutputStream(new FileOutputStream(fileSource))) { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = input.read(buffer)) != -1) { + output.write(buffer, 0, bytesRead); + } + } + } public String readAllText(String encoding)throws IOException{ return SpecificImplementation.FileUtils.readFileToString(fileSource, CommonUtil.normalizeEncodingName(encoding)); } diff --git a/gxcloudstorage-awss3-v1/src/main/java/com/genexus/db/driver/ExternalProviderS3V1.java b/gxcloudstorage-awss3-v1/src/main/java/com/genexus/db/driver/ExternalProviderS3V1.java index bebdc4c84..6ee1dd79e 100644 --- a/gxcloudstorage-awss3-v1/src/main/java/com/genexus/db/driver/ExternalProviderS3V1.java +++ b/gxcloudstorage-awss3-v1/src/main/java/com/genexus/db/driver/ExternalProviderS3V1.java @@ -17,7 +17,6 @@ import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; -import com.amazonaws.util.IOUtils; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -220,19 +219,14 @@ else if (acl == ResourceAccessControlList.PublicReadWrite) { } public String upload(String externalFileName, InputStream input, ResourceAccessControlList acl) { - byte[] bytes; - try { - bytes = IOUtils.toByteArray(input); + try (ExternalProviderHelper.InputStreamWithLength streamInfo = ExternalProviderHelper.getInputStreamContentLength(input)) { ObjectMetadata metadata = new ObjectMetadata(); - metadata.setContentLength(bytes.length); - if (externalFileName.endsWith(".tmp")) { - metadata.setContentType("image/jpeg"); - } + metadata.setContentLength(streamInfo.contentLength); + metadata.setContentType((externalFileName.endsWith(".tmp") && "application/octet-stream".equals(streamInfo.detectedContentType)) ? "image/jpeg" : streamInfo.detectedContentType); + String upload = ""; - try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes)) { - client.putObject(new PutObjectRequest(bucket, externalFileName, byteArrayInputStream, metadata).withCannedAcl(internalToAWSACL(acl))); - upload = getResourceUrl(externalFileName, acl, defaultExpirationMinutes); - } + client.putObject(new PutObjectRequest(bucket, externalFileName, streamInfo.inputStream, metadata).withCannedAcl(internalToAWSACL(acl))); + upload = getResourceUrl(externalFileName, acl, defaultExpirationMinutes); return upload; } catch (IOException ex) { logger.error("Error while uploading file to the external provider.", ex); diff --git a/gxcloudstorage-awss3-v2/src/main/java/com/genexus/db/driver/ExternalProviderS3V2.java b/gxcloudstorage-awss3-v2/src/main/java/com/genexus/db/driver/ExternalProviderS3V2.java index 878f4947a..0da262412 100644 --- a/gxcloudstorage-awss3-v2/src/main/java/com/genexus/db/driver/ExternalProviderS3V2.java +++ b/gxcloudstorage-awss3-v2/src/main/java/com/genexus/db/driver/ExternalProviderS3V2.java @@ -21,13 +21,11 @@ import com.genexus.util.StorageUtils; import com.genexus.StructSdtMessages_Message; import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest; -import software.amazon.awssdk.utils.IoUtils; import java.io.*; import java.net.URI; import java.net.URL; import java.net.URLEncoder; -import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -603,8 +601,7 @@ else if (acl == ResourceAccessControlList.PublicReadWrite) } private String uploadWithACL(String externalFileName, InputStream input, ResourceAccessControlList acl) { - try { - ByteBuffer byteBuffer = ByteBuffer.wrap(IoUtils.toByteArray(input)); + try (ExternalProviderHelper.InputStreamWithLength streamInfo = ExternalProviderHelper.getInputStreamContentLength(input)) { PutObjectRequest.Builder putObjectRequestBuilder = PutObjectRequest.builder() .bucket(bucket) .key(externalFileName) @@ -613,7 +610,7 @@ private String uploadWithACL(String externalFileName, InputStream input, Resourc putObjectRequestBuilder = putObjectRequestBuilder.acl(internalToAWSACLWithACL(acl)); PutObjectRequest putObjectRequest = putObjectRequestBuilder.build(); - PutObjectResponse response = client.putObject(putObjectRequest, RequestBody.fromByteBuffer(byteBuffer)); + PutObjectResponse response = client.putObject(putObjectRequest, RequestBody.fromInputStream(streamInfo.inputStream, streamInfo.contentLength)); if (!response.sdkHttpResponse().isSuccessful()) { logger.error("Error while uploading file: " + response.sdkHttpResponse().statusText().orElse("Unknown error")); } @@ -727,15 +724,14 @@ private String uploadWithoutACL(String localFile, String externalFileName) { } private String uploadWithoutACL(String externalFileName, InputStream input) { - try { - ByteBuffer byteBuffer = ByteBuffer.wrap(IoUtils.toByteArray(input)); + try (ExternalProviderHelper.InputStreamWithLength streamInfo = ExternalProviderHelper.getInputStreamContentLength(input)) { PutObjectRequest.Builder putObjectRequestBuilder = PutObjectRequest.builder() .bucket(bucket) .key(externalFileName) - .contentType(externalFileName.endsWith(".tmp") ? "image/jpeg" : null); + .contentType((externalFileName.endsWith(".tmp") && "application/octet-stream".equals(streamInfo.detectedContentType)) ? "image/jpeg" : streamInfo.detectedContentType); PutObjectRequest putObjectRequest = putObjectRequestBuilder.build(); - PutObjectResponse response = client.putObject(putObjectRequest, RequestBody.fromByteBuffer(byteBuffer)); + PutObjectResponse response = client.putObject(putObjectRequest, RequestBody.fromInputStream(streamInfo.inputStream, streamInfo.contentLength)); if (!response.sdkHttpResponse().isSuccessful()) { logger.error("Error while uploading file: " + response.sdkHttpResponse().statusText().orElse("Unknown error")); } diff --git a/gxcloudstorage-azureblob/src/main/java/com/genexus/db/driver/ExternalProviderAzureStorage.java b/gxcloudstorage-azureblob/src/main/java/com/genexus/db/driver/ExternalProviderAzureStorage.java index ed25d917b..723ea9eca 100644 --- a/gxcloudstorage-azureblob/src/main/java/com/genexus/db/driver/ExternalProviderAzureStorage.java +++ b/gxcloudstorage-azureblob/src/main/java/com/genexus/db/driver/ExternalProviderAzureStorage.java @@ -139,17 +139,14 @@ public String upload(String localFile, String externalFileName, ResourceAccessCo } public String upload(String externalFileName, InputStream input, ResourceAccessControlList acl) { - - try { + try (ExternalProviderHelper.InputStreamWithLength streamInfo = ExternalProviderHelper.getInputStreamContentLength(input)) { CloudBlockBlob blob = getCloudBlockBlob(externalFileName, acl); - if (externalFileName.endsWith(".tmp")) { - blob.getProperties().setContentType("image/jpeg"); - } + blob.getProperties().setContentType((externalFileName.endsWith(".tmp") && "application/octet-stream".equals(streamInfo.detectedContentType)) ? "image/jpeg" : streamInfo.detectedContentType); try (BlobOutputStream blobOutputStream = blob.openOutputStream()) { - int next = input.read(); - while (next != -1) { - blobOutputStream.write(next); - next = input.read(); + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = streamInfo.inputStream.read(buffer)) != -1) { + blobOutputStream.write(buffer, 0, bytesRead); } } return getResourceUrl(externalFileName, acl, DEFAULT_EXPIRATION_MINUTES); diff --git a/gxcloudstorage-common/pom.xml b/gxcloudstorage-common/pom.xml index 8f8724f1c..c09876e36 100644 --- a/gxcloudstorage-common/pom.xml +++ b/gxcloudstorage-common/pom.xml @@ -34,6 +34,16 @@ log4j-api ${log4j.version} + + org.apache.logging.log4j + log4j-slf4j2-impl + ${log4j.version} + + + org.apache.tika + tika-core + 2.9.4 + diff --git a/gxcloudstorage-common/src/main/java/com/genexus/db/driver/ExternalProviderHelper.java b/gxcloudstorage-common/src/main/java/com/genexus/db/driver/ExternalProviderHelper.java index fb8710752..c514b639b 100644 --- a/gxcloudstorage-common/src/main/java/com/genexus/db/driver/ExternalProviderHelper.java +++ b/gxcloudstorage-common/src/main/java/com/genexus/db/driver/ExternalProviderHelper.java @@ -3,8 +3,13 @@ import com.genexus.util.Encryption; import com.genexus.util.GXService; +import java.io.*; +import org.apache.tika.Tika; + public class ExternalProviderHelper { + public static final int BUFFER_MARK_LIMIT = 128 * 1024; + public static String getServicePropertyValue(GXService s, String propName, boolean isSecure){ String value = s.getProperties().get(propName); if (value != null){ @@ -23,4 +28,49 @@ public static String getEnvironmentVariable(String name, boolean required) throw } return value; } + + public static InputStreamWithLength getInputStreamContentLength(InputStream input) throws IOException { + File tempFile = File.createTempFile("upload-", ".tmp"); + try (OutputStream out = new FileOutputStream(tempFile)) { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = input.read(buffer)) != -1) { + out.write(buffer, 0, bytesRead); + } + } + long size = tempFile.length(); + InputStream bufferedInput = new BufferedInputStream(new FileInputStream(tempFile)); + bufferedInput.mark(BUFFER_MARK_LIMIT); + Tika tika = new Tika(); + String detectedContentType = tika.detect(bufferedInput); + bufferedInput.reset(); + return new InputStreamWithLength(bufferedInput, size, tempFile, detectedContentType); + } + + public static class InputStreamWithLength implements AutoCloseable { + public final InputStream inputStream; + public final long contentLength; + public final File tempFile; // nullable + public final String detectedContentType; + + public InputStreamWithLength(InputStream inputStream, long contentLength, File tempFile, String detectedContentType) { + this.inputStream = inputStream; + this.contentLength = contentLength; + this.tempFile = tempFile; + this.detectedContentType = detectedContentType; + } + + @Override + public void close() throws IOException { + try { + if (inputStream != null) { + inputStream.close(); + } + } finally { + if (tempFile != null && tempFile.exists()) { + tempFile.delete(); + } + } + } + } } diff --git a/gxcloudstorage-googlecloudstorage/src/main/java/com/genexus/db/driver/ExternalProviderGoogle.java b/gxcloudstorage-googlecloudstorage/src/main/java/com/genexus/db/driver/ExternalProviderGoogle.java index 7c39c45a0..f1220b19d 100644 --- a/gxcloudstorage-googlecloudstorage/src/main/java/com/genexus/db/driver/ExternalProviderGoogle.java +++ b/gxcloudstorage-googlecloudstorage/src/main/java/com/genexus/db/driver/ExternalProviderGoogle.java @@ -16,7 +16,6 @@ import com.google.api.services.storage.model.StorageObject; import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.cloud.storage.*; -import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -170,11 +169,12 @@ private void setBlobAcl(BlobId blobId, ResourceAccessControlList acl) { } public String upload(String externalFileName, InputStream input, ResourceAccessControlList acl) { - try { + try (ExternalProviderHelper.InputStreamWithLength streamInfo = ExternalProviderHelper.getInputStreamContentLength(input)) { BlobId blobId = BlobId.of(bucket, externalFileName); BlobInfo blobInfo = BlobInfo.newBuilder(blobId).build(); - byte[] targetArray = IOUtils.toByteArray(input); - storageClient.create(blobInfo, targetArray); + + storageClient.createFrom(blobInfo, streamInfo.tempFile.toPath()); + setBlobAcl(blobId, acl); return getResourceUrl(blobInfo, acl); } catch (IOException ex) { diff --git a/gxcloudstorage-ibmcos/src/main/java/com/genexus/db/driver/ExternalProviderIBM.java b/gxcloudstorage-ibmcos/src/main/java/com/genexus/db/driver/ExternalProviderIBM.java index b38c8eb4b..18dbf8ec2 100644 --- a/gxcloudstorage-ibmcos/src/main/java/com/genexus/db/driver/ExternalProviderIBM.java +++ b/gxcloudstorage-ibmcos/src/main/java/com/genexus/db/driver/ExternalProviderIBM.java @@ -14,7 +14,6 @@ import com.ibm.cloud.objectstorage.services.s3.AmazonS3Client; import com.ibm.cloud.objectstorage.services.s3.AmazonS3ClientBuilder; import com.ibm.cloud.objectstorage.services.s3.model.*; -import com.ibm.cloud.objectstorage.util.IOUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -150,19 +149,13 @@ else if (acl == ResourceAccessControlList.PublicReadWrite) { } public String upload(String externalFileName, InputStream input, ResourceAccessControlList acl) { - byte[] bytes; - try { - bytes = IOUtils.toByteArray(input); + try (ExternalProviderHelper.InputStreamWithLength streamInfo = ExternalProviderHelper.getInputStreamContentLength(input)) { ObjectMetadata metadata = new ObjectMetadata(); - metadata.setContentLength(bytes.length); - if (externalFileName.endsWith(".tmp")) { - metadata.setContentType("image/jpeg"); - } + metadata.setContentLength(streamInfo.contentLength); + metadata.setContentType((externalFileName.endsWith(".tmp") && "application/octet-stream".equals(streamInfo.detectedContentType)) ? "image/jpeg" : streamInfo.detectedContentType); String upload = ""; - try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes)) { - client.putObject(new PutObjectRequest(bucket, externalFileName, byteArrayInputStream, metadata).withCannedAcl(internalToAWSACL(acl))); - upload = getResourceUrl(externalFileName, acl, defaultExpirationMinutes); - } + client.putObject(new PutObjectRequest(bucket, externalFileName, streamInfo.inputStream, metadata).withCannedAcl(internalToAWSACL(acl))); + upload = getResourceUrl(externalFileName, acl, defaultExpirationMinutes); return upload; } catch (IOException ex) { logger.error("Error while uploading file to the external provider.", ex); diff --git a/java/pom.xml b/java/pom.xml index 6c03bd23a..6f69f9e61 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -59,11 +59,6 @@ javax.jms 3.1.2.2 - - commons-io - commons-io - 2.11.0 - commons-net commons-net diff --git a/wrappercommon/pom.xml b/wrappercommon/pom.xml index b52622955..c94606440 100644 --- a/wrappercommon/pom.xml +++ b/wrappercommon/pom.xml @@ -29,11 +29,6 @@ log4j-core ${log4j.version} - - commons-io - commons-io - 2.11.0 - org.apache.ws.security wss4j