Bug 442576 - Allow to disable WebDav support Added configuration property aether.connector.http.webDav[.repoId] to forcefully disable WebDAV mode during uploads
Project: http://git-wip-us.apache.org/repos/asf/maven-aether/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-aether/commit/cd3cb86f Tree: http://git-wip-us.apache.org/repos/asf/maven-aether/tree/cd3cb86f Diff: http://git-wip-us.apache.org/repos/asf/maven-aether/diff/cd3cb86f Branch: refs/heads/master Commit: cd3cb86f23644784e43b8fc2ae166b6a312b6073 Parents: 6ac187b Author: Benjamin Bentmann <bentm...@sonatype.com> Authored: Sat Aug 30 21:25:06 2014 +0200 Committer: Benjamin Bentmann <bentm...@sonatype.com> Committed: Sat Aug 30 21:25:06 2014 +0200 ---------------------------------------------------------------------- .../aether/transport/http/HttpTransporter.java | 36 +++++++++++++------- .../aether/transport/http/LocalState.java | 30 +++++++++++++--- .../aether/transport/http/HttpServer.java | 25 ++++++++++---- .../transport/http/HttpTransporterTest.java | 33 ++++++++++++++++-- 4 files changed, 99 insertions(+), 25 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-aether/blob/cd3cb86f/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java ---------------------------------------------------------------------- diff --git a/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java b/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java index 4e21949..a801373 100644 --- a/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java +++ b/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Sonatype, Inc. + * Copyright (c) 2013, 2014 Sonatype, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -304,26 +304,38 @@ final class HttpTransporter private void prepare( HttpUriRequest request, SharingHttpContext context ) { boolean put = HttpPut.METHOD_NAME.equalsIgnoreCase( request.getMethod() ); - if ( state.getWebDav() == null && ( put || isPayloadPresent( request ) ) ) + if ( ( put || isPayloadPresent( request ) ) && !state.isProbed() ) { - try - { - HttpOptions req = commonHeaders( new HttpOptions( request.getURI() ) ); - HttpResponse response = client.execute( server, req, context ); - state.setWebDav( isWebDav( response ) ); - EntityUtils.consumeQuietly( response.getEntity() ); - } - catch ( IOException e ) + synchronized ( state ) { - logger.debug( "Failed to prepare HTTP context", e ); + if ( !state.isProbed() ) + { + probe( request, context ); + state.setProbed(); + } } } - if ( put && Boolean.TRUE.equals( state.getWebDav() ) ) + if ( put && state.isWebDav() ) { mkdirs( request.getURI(), context ); } } + private void probe( HttpUriRequest request, SharingHttpContext context ) + { + try + { + HttpOptions req = commonHeaders( new HttpOptions( request.getURI() ) ); + HttpResponse response = client.execute( server, req, context ); + state.setWebDav( isWebDav( response ) ); + EntityUtils.consumeQuietly( response.getEntity() ); + } + catch ( IOException e ) + { + logger.debug( "Failed to probe HTTP server", e ); + } + } + private boolean isWebDav( HttpResponse response ) { return response.containsHeader( HttpHeaders.DAV ); http://git-wip-us.apache.org/repos/asf/maven-aether/blob/cd3cb86f/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/LocalState.java ---------------------------------------------------------------------- diff --git a/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/LocalState.java b/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/LocalState.java index 8275973..1cc771d 100644 --- a/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/LocalState.java +++ b/aether-transport-http/src/main/java/org/eclipse/aether/transport/http/LocalState.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Sonatype, Inc. + * Copyright (c) 2013, 2014 Sonatype, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -20,6 +20,7 @@ import org.apache.http.conn.ClientConnectionManager; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.transport.http.GlobalState.CompoundKey; +import org.eclipse.aether.util.ConfigUtils; /** * Container for HTTP-related state that can be shared across invocations of the transporter to optimize the @@ -29,6 +30,8 @@ final class LocalState implements Closeable { + private static final String CONFIG_PROP_WEBDAV = "aether.connector.http.webDav"; + private final GlobalState global; private final ClientConnectionManager connMgr; @@ -39,6 +42,8 @@ final class LocalState private final CompoundKey expectContinueKey; + private volatile boolean probed; + private volatile Boolean expectContinue; private volatile Boolean webDav; @@ -63,6 +68,10 @@ final class LocalState expectContinueKey = new CompoundKey( repo.getUrl(), repo.getProxy() ); authSchemePools = global.getAuthSchemePools(); } + if ( !ConfigUtils.getBoolean( session, true, CONFIG_PROP_WEBDAV + '.' + repo.getId(), CONFIG_PROP_WEBDAV ) ) + { + webDav = false; + } } public ClientConnectionManager getConnectionManager() @@ -88,6 +97,16 @@ final class LocalState } } + public boolean isProbed() + { + return probed; + } + + public void setProbed() + { + probed = true; + } + public boolean isExpectContinue() { if ( expectContinue == null ) @@ -107,14 +126,17 @@ final class LocalState } } - public Boolean getWebDav() + public boolean isWebDav() { - return webDav; + return Boolean.TRUE.equals( webDav ); } public void setWebDav( boolean webDav ) { - this.webDav = webDav; + if ( this.webDav == null ) + { + this.webDav = webDav; + } } public AuthScheme getAuthScheme( HttpHost host ) http://git-wip-us.apache.org/repos/asf/maven-aether/blob/cd3cb86f/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpServer.java ---------------------------------------------------------------------- diff --git a/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpServer.java b/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpServer.java index a0f6a54..60f316a 100644 --- a/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpServer.java +++ b/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpServer.java @@ -72,9 +72,22 @@ public class HttpServer } + public enum WebDav + { + /** DAV header advertised, MKCOL required for missing parent directories */ + REQUIRED, + /** DAV header advertised, MKCOL supported but not required */ + OPTIONAL + } + public enum ExpectContinue { - FAIL, PROPER, BROKEN + /** reject request with "Expectation Failed" */ + FAIL, + /** send "Continue" only if request made it past authentication */ + PROPER, + /** send "Continue" before authentication has been checked */ + BROKEN } public enum ChecksumHeader @@ -90,7 +103,7 @@ public class HttpServer private boolean rangeSupport = true; - private boolean webDav; + private WebDav webDav; private ExpectContinue expectContinue = ExpectContinue.PROPER; @@ -186,7 +199,7 @@ public class HttpServer return this; } - public HttpServer setWebDav( boolean webDav ) + public HttpServer setWebDav( WebDav webDav ) { this.webDav = webDav; return this; @@ -405,7 +418,7 @@ public class HttpServer } else if ( HttpMethods.PUT.equals( req.getMethod() ) ) { - if ( !webDav ) + if ( !WebDav.REQUIRED.equals( webDav ) ) { file.getParentFile().mkdirs(); } @@ -437,14 +450,14 @@ public class HttpServer } else if ( HttpMethods.OPTIONS.equals( req.getMethod() ) ) { - if ( webDav ) + if ( webDav != null ) { response.setHeader( "DAV", "1,2" ); } response.setHeader( HttpHeaders.ALLOW, "GET, PUT, HEAD, OPTIONS" ); response.setStatus( HttpServletResponse.SC_OK ); } - else if ( webDav && "MKCOL".equals( req.getMethod() ) ) + else if ( webDav != null && "MKCOL".equals( req.getMethod() ) ) { if ( file.exists() ) { http://git-wip-us.apache.org/repos/asf/maven-aether/blob/cd3cb86f/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java ---------------------------------------------------------------------- diff --git a/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java b/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java index 8a36861..14ec31e 100644 --- a/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java +++ b/aether-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java @@ -64,6 +64,8 @@ public class HttpTransporterTest System.setProperty( "javax.net.ssl.keyStorePassword", "client-pwd" ); } + private static final String REPO_ID = "test"; + @Rule public TestName testName = new TestName(); @@ -83,7 +85,7 @@ public class HttpTransporterTest private RemoteRepository newRepo( String url ) { - return new RemoteRepository.Builder( "test", "default", url ).setAuthentication( auth ).setProxy( proxy ).build(); + return new RemoteRepository.Builder( REPO_ID, "default", url ).setAuthentication( auth ).setProxy( proxy ).build(); } private void newTransporter( String url ) @@ -406,7 +408,7 @@ public class HttpTransporterTest public void testGet_WebDav() throws Exception { - httpServer.setWebDav( true ); + httpServer.setWebDav( HttpServer.WebDav.REQUIRED ); RecordingTransportListener listener = new RecordingTransportListener(); GetTask task = new GetTask( URI.create( "repo/dir/file.txt" ) ).setListener( listener ); ( (HttpTransporter) transporter ).getState().setWebDav( true ); @@ -801,7 +803,7 @@ public class HttpTransporterTest public void testPut_WebDav() throws Exception { - httpServer.setWebDav( true ); + httpServer.setWebDav( HttpServer.WebDav.REQUIRED ); RecordingTransportListener listener = new RecordingTransportListener(); PutTask task = new PutTask( URI.create( "repo/dir1/dir2/file.txt" ) ).setListener( listener ).setDataString( "upload" ); @@ -824,6 +826,31 @@ public class HttpTransporterTest } @Test + public void testPut_WebDavOptional_ManuallyDisabled() + throws Exception + { + session.setConfigProperty( "aether.connector.http.webDav." + REPO_ID, "false" ); + httpServer.setWebDav( HttpServer.WebDav.OPTIONAL ); + httpServer.setAuthentication( "testuser", "testpass" ); + auth = new AuthenticationBuilder().addUsername( "testuser" ).addPassword( "testpass" ).build(); + newTransporter( httpServer.getHttpUrl() ); + RecordingTransportListener listener = new RecordingTransportListener(); + PutTask task = + new PutTask( URI.create( "repo/dir1/dir2/file.txt" ) ).setListener( listener ).setDataString( "upload" ); + transporter.put( task ); + assertEquals( 0, listener.dataOffset ); + assertEquals( 6, listener.dataLength ); + assertEquals( 1, listener.startedCount ); + assertTrue( "Count: " + listener.progressedCount, listener.progressedCount > 0 ); + assertEquals( "upload", TestFileUtils.readString( new File( repoDir, "dir1/dir2/file.txt" ) ) ); + + assertEquals( httpServer.getLogEntries().toString(), 3, httpServer.getLogEntries().size() ); + assertEquals( "OPTIONS", httpServer.getLogEntries().get( 0 ).method ); + assertEquals( "OPTIONS", httpServer.getLogEntries().get( 1 ).method ); + assertEquals( "PUT", httpServer.getLogEntries().get( 2 ).method ); + } + + @Test public void testPut_FileHandleLeak() throws Exception {