From 3ae49fcaf39cf2e563720696132bb1c07d7b0c57 Mon Sep 17 00:00:00 2001 From: Chris Beckey Date: Thu, 6 Aug 2020 09:19:08 -0400 Subject: [PATCH 01/10] determine the content type from file extension and set content-type header if that is not empty --- .../maven/wagon/shared/http/AbstractHttpClientWagon.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java index 3e9fe91ff..f5d11cc30 100644 --- a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java +++ b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java @@ -82,6 +82,7 @@ import org.apache.maven.wagon.resource.Resource; import org.codehaus.plexus.util.StringUtils; +import javax.activation.MimetypesFileTypeMap; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import java.io.Closeable; @@ -119,6 +120,8 @@ public abstract class AbstractHttpClientWagon extends StreamWagon { + private static final MimetypesFileTypeMap FILE_TYPE_MAP = new MimetypesFileTypeMap(); + final class WagonHttpEntity extends AbstractHttpEntity { @@ -142,6 +145,11 @@ private WagonHttpEntity( final InputStream stream, final Resource resource, fina { this.source = source; this.repeatable = true; + final String mimeType = FILE_TYPE_MAP.getContentType( source ); + if ( mimeType != null && !mimeType.isEmpty() ) + { + setContentType( mimeType ); + } } else { @@ -152,6 +160,7 @@ private WagonHttpEntity( final InputStream stream, final Resource resource, fina this.length = resource == null ? -1 : resource.getContentLength(); this.wagon = wagon; + } public Resource getResource() From 002b8be84a141e2ff1557990a835dfe06be087e6 Mon Sep 17 00:00:00 2001 From: Chris Beckey Date: Thu, 6 Aug 2020 09:29:39 -0400 Subject: [PATCH 02/10] added system property to control determination of content type from file extension --- .../maven/wagon/shared/http/AbstractHttpClientWagon.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java index f5d11cc30..3f4a6eb11 100644 --- a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java +++ b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java @@ -145,7 +145,7 @@ private WagonHttpEntity( final InputStream stream, final Resource resource, fina { this.source = source; this.repeatable = true; - final String mimeType = FILE_TYPE_MAP.getContentType( source ); + final String mimeType = SET_CONTENT_TYPE_FROM_FILE_EXTENSION ? FILE_TYPE_MAP.getContentType( source ) : null; if ( mimeType != null && !mimeType.isEmpty() ) { setContentType( mimeType ); @@ -288,6 +288,12 @@ public boolean isStreaming() private static final boolean SSL_ALLOW_ALL = Boolean.valueOf( System.getProperty( "maven.wagon.http.ssl.allowall", "false" ) ); + /** + * If enabled, ssl hostname verifier does not check hostname. Disable this will use a browser compat hostname + * verifier disabled by default + */ + private static final boolean SET_CONTENT_TYPE_FROM_FILE_EXTENSION = + Boolean.valueOf( System.getProperty( "maven.wagon.http.file.autocontenttype", "false" ) ); /** * Maximum concurrent connections per distinct route. From eb70394d44e1c78a42fd949ccbd4a42239c85403 Mon Sep 17 00:00:00 2001 From: Chris Beckey Date: Thu, 6 Aug 2020 09:42:50 -0400 Subject: [PATCH 03/10] correct checkstyle error --- .../maven/wagon/shared/http/AbstractHttpClientWagon.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java index 3f4a6eb11..b658014c7 100644 --- a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java +++ b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java @@ -145,7 +145,9 @@ private WagonHttpEntity( final InputStream stream, final Resource resource, fina { this.source = source; this.repeatable = true; - final String mimeType = SET_CONTENT_TYPE_FROM_FILE_EXTENSION ? FILE_TYPE_MAP.getContentType( source ) : null; + final String mimeType = SET_CONTENT_TYPE_FROM_FILE_EXTENSION + ? FILE_TYPE_MAP.getContentType( source ) + : null; if ( mimeType != null && !mimeType.isEmpty() ) { setContentType( mimeType ); From e71d0d3038c17124c9b88b1ee11d78942aa10b0e Mon Sep 17 00:00:00 2001 From: Chris Beckey Date: Thu, 6 Aug 2020 10:03:42 -0400 Subject: [PATCH 04/10] fixed comment on system property (flag) --- .../maven/wagon/shared/http/AbstractHttpClientWagon.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java index b658014c7..c680ecb16 100644 --- a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java +++ b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java @@ -291,8 +291,9 @@ public boolean isStreaming() Boolean.valueOf( System.getProperty( "maven.wagon.http.ssl.allowall", "false" ) ); /** - * If enabled, ssl hostname verifier does not check hostname. Disable this will use a browser compat hostname - * verifier disabled by default + * If enabled, then the content-type HTTP header will be set using the file extension to determine the type, + * disabled by default + * This flag is only effective when uploading from a File, not directly from a Stream. */ private static final boolean SET_CONTENT_TYPE_FROM_FILE_EXTENSION = Boolean.valueOf( System.getProperty( "maven.wagon.http.file.autocontenttype", "false" ) ); From d4563016f761090576b8bb3d06571b93069b16ce Mon Sep 17 00:00:00 2001 From: Chris Beckey Date: Thu, 6 Aug 2020 10:52:20 -0400 Subject: [PATCH 05/10] add conditional on existing content-type and handle JDK11 activation lib removal --- wagon-providers/pom.xml | 16 ++++++++++++++++ .../shared/http/AbstractHttpClientWagon.java | 16 +++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/wagon-providers/pom.xml b/wagon-providers/pom.xml index 6f1983a6c..6f3fbca42 100644 --- a/wagon-providers/pom.xml +++ b/wagon-providers/pom.xml @@ -78,4 +78,20 @@ under the License. test + + + + jdk11 + + [1.11,) + + + + com.sun.activation + javax.activation + 1.2.0 + + + + diff --git a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java index c680ecb16..101fe6de1 100644 --- a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java +++ b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java @@ -145,12 +145,18 @@ private WagonHttpEntity( final InputStream stream, final Resource resource, fina { this.source = source; this.repeatable = true; - final String mimeType = SET_CONTENT_TYPE_FROM_FILE_EXTENSION - ? FILE_TYPE_MAP.getContentType( source ) - : null; - if ( mimeType != null && !mimeType.isEmpty() ) + // if the content-type has not been set then + // if the option flag is TRUE and the content type is determinable from the file extension + // then set it from the file extension + if ( getContentType() == null ) { - setContentType( mimeType ); + final String mimeType = SET_CONTENT_TYPE_FROM_FILE_EXTENSION + ? FILE_TYPE_MAP.getContentType( source ) + : null; + if ( mimeType != null && !mimeType.isEmpty() ) + { + setContentType( mimeType ); + } } } else From 51a6fd742061db3452e39eefee0465ae75747f27 Mon Sep 17 00:00:00 2001 From: Chris Beckey Date: Thu, 6 Aug 2020 12:44:54 -0400 Subject: [PATCH 06/10] removed dependency on javax.activation, use URLConnection rather than File extension to mime type map. --- wagon-providers/pom.xml | 15 ---- .../shared/http/AbstractHttpClientWagon.java | 70 +++++++++++++------ 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/wagon-providers/pom.xml b/wagon-providers/pom.xml index 6f3fbca42..7c5cbed42 100644 --- a/wagon-providers/pom.xml +++ b/wagon-providers/pom.xml @@ -79,19 +79,4 @@ under the License. - - - jdk11 - - [1.11,) - - - - com.sun.activation - javax.activation - 1.2.0 - - - - diff --git a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java index 101fe6de1..17faf578a 100644 --- a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java +++ b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java @@ -82,7 +82,6 @@ import org.apache.maven.wagon.resource.Resource; import org.codehaus.plexus.util.StringUtils; -import javax.activation.MimetypesFileTypeMap; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import java.io.Closeable; @@ -92,6 +91,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; +import java.net.URLConnection; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.channels.Channels; @@ -120,8 +120,6 @@ public abstract class AbstractHttpClientWagon extends StreamWagon { - private static final MimetypesFileTypeMap FILE_TYPE_MAP = new MimetypesFileTypeMap(); - final class WagonHttpEntity extends AbstractHttpEntity { @@ -145,19 +143,6 @@ private WagonHttpEntity( final InputStream stream, final Resource resource, fina { this.source = source; this.repeatable = true; - // if the content-type has not been set then - // if the option flag is TRUE and the content type is determinable from the file extension - // then set it from the file extension - if ( getContentType() == null ) - { - final String mimeType = SET_CONTENT_TYPE_FROM_FILE_EXTENSION - ? FILE_TYPE_MAP.getContentType( source ) - : null; - if ( mimeType != null && !mimeType.isEmpty() ) - { - setContentType( mimeType ); - } - } } else { @@ -169,6 +154,44 @@ private WagonHttpEntity( final InputStream stream, final Resource resource, fina this.wagon = wagon; + // if the autoset content flag is SET and the content type is blank + // then try to determine what the content type is and set it + if ( AUTOSET_CONTENT_TYPE && getContentType() == null ) + { + try + { + autosetContentType(); + } + catch ( IOException ioX ) + { + if ( AUTOSET_CONTENT_TYPE_FATAL ) + { + throw new TransferFailedException( + "Failed to determine content type, " + + " unset 'maven.wagon.http.autocontenttype.fatal' to allow continued processing", + ioX ); + } + } + } + } + + private void autosetContentType() throws IOException + { + // if the content-type has not been set then + // if the option flag is TRUE and the content type is determinable from the file extension + // then set it from the file extension + final String mimeType = AUTOSET_CONTENT_TYPE + ? this.source != null + ? URLConnection.guessContentTypeFromName( source.getName() ) + : this.stream != null + ? URLConnection.guessContentTypeFromStream( this.stream ) + : null + : null; + if ( mimeType != null && !mimeType.isEmpty() ) + { + setContentType( mimeType ); + } + } public Resource getResource() @@ -297,12 +320,19 @@ public boolean isStreaming() Boolean.valueOf( System.getProperty( "maven.wagon.http.ssl.allowall", "false" ) ); /** - * If enabled, then the content-type HTTP header will be set using the file extension to determine the type, + * If enabled, then the content-type HTTP header will be set using the file extension + * or the stream header to determine the type, disabled by default + */ + private static final boolean AUTOSET_CONTENT_TYPE = + Boolean.valueOf( System.getProperty( "maven.wagon.http.autocontenttype", "true" ) ); + + /** + * If enabled, then an when determining the content type will result in a fatal exception * disabled by default - * This flag is only effective when uploading from a File, not directly from a Stream. + * This flag is only effective when maven.wagon.http.autocontenttype is set. */ - private static final boolean SET_CONTENT_TYPE_FROM_FILE_EXTENSION = - Boolean.valueOf( System.getProperty( "maven.wagon.http.file.autocontenttype", "false" ) ); + private static final boolean AUTOSET_CONTENT_TYPE_FATAL = + Boolean.valueOf( System.getProperty( "maven.wagon.http.autocontenttype.fatal", "false" ) ); /** * Maximum concurrent connections per distinct route. From 928a393821e288175aaa4b5d1aee06506a0c8928 Mon Sep 17 00:00:00 2001 From: Chris Beckey Date: Thu, 6 Aug 2020 13:51:02 -0400 Subject: [PATCH 07/10] added a comment to indicate behavior of URLConnection.guessContentTypeFromStream() --- .../shared/http/AbstractHttpClientWagon.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java index 17faf578a..00515c205 100644 --- a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java +++ b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java @@ -175,11 +175,24 @@ private WagonHttpEntity( final InputStream stream, final Resource resource, fina } } + /** + * Try to determine the content type and set the content-type header if successful. + * + * if the content-type has not been set then + * if the (AUTOSET_CONTENT_TYPE) option flag is TRUE + * and + * the content is coming from a file and the content type is determinable from the file extension + * or + * the content is coming from a stream and the content type is determinable from the stream + * (guessContentTypeFromStream will return null if the InputStream does not support mark()) + * then determine and set the content type + * Note: the content-type will never be set to null or an empty string by this method. + * + * @throws IOException - indicates a failure when trying to determine the content type of a stream, will + * never occur when the content is coming from File + */ private void autosetContentType() throws IOException { - // if the content-type has not been set then - // if the option flag is TRUE and the content type is determinable from the file extension - // then set it from the file extension final String mimeType = AUTOSET_CONTENT_TYPE ? this.source != null ? URLConnection.guessContentTypeFromName( source.getName() ) From 4ea523b4c0c685604a4eaa7a8dcc2792d4f8e8f9 Mon Sep 17 00:00:00 2001 From: Chris Beckey Date: Thu, 6 Aug 2020 13:58:37 -0400 Subject: [PATCH 08/10] correct comment, autocontenttype is on by default --- .../apache/maven/wagon/shared/http/AbstractHttpClientWagon.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java index 00515c205..71ee04ccd 100644 --- a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java +++ b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java @@ -334,7 +334,7 @@ public boolean isStreaming() /** * If enabled, then the content-type HTTP header will be set using the file extension - * or the stream header to determine the type, disabled by default + * or the stream header to determine the type, enabled by default */ private static final boolean AUTOSET_CONTENT_TYPE = Boolean.valueOf( System.getProperty( "maven.wagon.http.autocontenttype", "true" ) ); From c9761c1bc0d68511187ac42b69c2bbb9fa4cbe42 Mon Sep 17 00:00:00 2001 From: Chris Beckey Date: Fri, 7 Aug 2020 11:25:54 -0400 Subject: [PATCH 09/10] if autoset is on SET then always set the content-type, remove optional exception behavior --- .../shared/http/AbstractHttpClientWagon.java | 70 ++++++++----------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java index 71ee04ccd..2ddddba83 100644 --- a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java +++ b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java @@ -123,6 +123,7 @@ public abstract class AbstractHttpClientWagon final class WagonHttpEntity extends AbstractHttpEntity { + public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream"; private final Resource resource; private final Wagon wagon; @@ -158,53 +159,46 @@ private WagonHttpEntity( final InputStream stream, final Resource resource, fina // then try to determine what the content type is and set it if ( AUTOSET_CONTENT_TYPE && getContentType() == null ) { - try - { - autosetContentType(); - } - catch ( IOException ioX ) - { - if ( AUTOSET_CONTENT_TYPE_FATAL ) - { - throw new TransferFailedException( - "Failed to determine content type, " - + " unset 'maven.wagon.http.autocontenttype.fatal' to allow continued processing", - ioX ); - } - } + setContentType( determineContentType() ); } } /** - * Try to determine the content type and set the content-type header if successful. + * Best effort to determine the content type. * - * if the content-type has not been set then - * if the (AUTOSET_CONTENT_TYPE) option flag is TRUE - * and - * the content is coming from a file and the content type is determinable from the file extension + * if the content is coming from a file and the content type is determinable from the file extension * or - * the content is coming from a stream and the content type is determinable from the stream + * if the content is coming from a stream and the content type is determinable from the stream * (guessContentTypeFromStream will return null if the InputStream does not support mark()) - * then determine and set the content type - * Note: the content-type will never be set to null or an empty string by this method. + * then determine and return the content type + * if the content type is not determinable then return "application/octet-stream" * - * @throws IOException - indicates a failure when trying to determine the content type of a stream, will - * never occur when the content is coming from File + * NOTE: this method is expected to always return a non-empty String */ - private void autosetContentType() throws IOException + private String determineContentType() { - final String mimeType = AUTOSET_CONTENT_TYPE - ? this.source != null - ? URLConnection.guessContentTypeFromName( source.getName() ) - : this.stream != null - ? URLConnection.guessContentTypeFromStream( this.stream ) - : null - : null; - if ( mimeType != null && !mimeType.isEmpty() ) + String mimeType; + try { - setContentType( mimeType ); + mimeType = this.source != null + ? URLConnection.guessContentTypeFromName( this.source.getName() ) + : this.stream != null + ? URLConnection.guessContentTypeFromStream( this.stream ) + : DEFAULT_CONTENT_TYPE; + + // if URLConnection was unable to determine the type then default it + if ( mimeType == null ) + { + mimeType = DEFAULT_CONTENT_TYPE; + } + } + catch ( IOException e ) + { + // will only occur when guessContentTypeFromStream gets an IOException + mimeType = DEFAULT_CONTENT_TYPE; } + return mimeType; } public Resource getResource() @@ -339,14 +333,6 @@ public boolean isStreaming() private static final boolean AUTOSET_CONTENT_TYPE = Boolean.valueOf( System.getProperty( "maven.wagon.http.autocontenttype", "true" ) ); - /** - * If enabled, then an when determining the content type will result in a fatal exception - * disabled by default - * This flag is only effective when maven.wagon.http.autocontenttype is set. - */ - private static final boolean AUTOSET_CONTENT_TYPE_FATAL = - Boolean.valueOf( System.getProperty( "maven.wagon.http.autocontenttype.fatal", "false" ) ); - /** * Maximum concurrent connections per distinct route. * 20 by default From 3643d923c4bde1ace9c13f6092521f8656409794 Mon Sep 17 00:00:00 2001 From: Chris Beckey Date: Fri, 7 Aug 2020 12:37:29 -0400 Subject: [PATCH 10/10] moved declaration --- .../maven/wagon/shared/http/AbstractHttpClientWagon.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java index 2ddddba83..8c76ef7a7 100644 --- a/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java +++ b/wagon-providers/wagon-http-shared/src/main/java/org/apache/maven/wagon/shared/http/AbstractHttpClientWagon.java @@ -177,10 +177,9 @@ private WagonHttpEntity( final InputStream stream, final Resource resource, fina */ private String determineContentType() { - String mimeType; try { - mimeType = this.source != null + String mimeType = this.source != null ? URLConnection.guessContentTypeFromName( this.source.getName() ) : this.stream != null ? URLConnection.guessContentTypeFromStream( this.stream ) @@ -191,14 +190,13 @@ private String determineContentType() { mimeType = DEFAULT_CONTENT_TYPE; } + return mimeType; } catch ( IOException e ) { // will only occur when guessContentTypeFromStream gets an IOException - mimeType = DEFAULT_CONTENT_TYPE; + return DEFAULT_CONTENT_TYPE; } - - return mimeType; } public Resource getResource()