diff --git a/pom.xml b/pom.xml index b14822c8..ff4bcdf4 100644 --- a/pom.xml +++ b/pom.xml @@ -293,7 +293,8 @@ 11 false - 4.5.14 + 5.4.1 + 5.3.2 2.0.16 @@ -312,10 +313,20 @@ - org.apache.httpcomponents - httpclient + org.apache.httpcomponents.client5 + httpclient5 ${httpclient.version} + + org.apache.httpcomponents.core5 + httpcore5 + ${httpcore.version} + + + org.apache.httpcomponents.core5 + httpcore5-h2 + ${httpcore.version} + diff --git a/src/main/java/com/github/sardine/DavResource.java b/src/main/java/com/github/sardine/DavResource.java index 154e0852..e10bfdc9 100644 --- a/src/main/java/com/github/sardine/DavResource.java +++ b/src/main/java/com/github/sardine/DavResource.java @@ -20,9 +20,10 @@ import javax.xml.namespace.QName; -import org.apache.http.HttpStatus; -import org.apache.http.ParseException; -import org.apache.http.message.BasicLineParser; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.message.BasicLineParser; +import org.apache.hc.core5.util.CharArrayBuffer; import org.w3c.dom.Element; import com.github.sardine.model.Creationdate; @@ -172,7 +173,9 @@ private int getStatusCode(Response response) for(Propstat propstat : list) { if(propstat.getStatus() != null) { try { - return BasicLineParser.parseStatusLine(propstat.getStatus(), null).getStatusCode(); + CharArrayBuffer buffer = new CharArrayBuffer(propstat.getStatus().length()); + buffer.append(propstat.getStatus()); + return new BasicLineParser().parseStatusLine(buffer).getStatusCode(); } catch(ParseException e) { log.warning(String.format("Failed to parse status line: %s", propstat.getStatus())); @@ -187,7 +190,9 @@ private int getStatusCode(Response response) } try { - return BasicLineParser.parseStatusLine(response.getStatus(), null).getStatusCode(); + CharArrayBuffer buffer = new CharArrayBuffer(response.getStatus().length()); + buffer.append(response.getStatus()); + return new BasicLineParser().parseStatusLine(buffer).getStatusCode(); } catch (ParseException e) { diff --git a/src/main/java/com/github/sardine/Sardine.java b/src/main/java/com/github/sardine/Sardine.java index 728e4f47..593a5b42 100644 --- a/src/main/java/com/github/sardine/Sardine.java +++ b/src/main/java/com/github/sardine/Sardine.java @@ -7,12 +7,10 @@ import java.util.List; import java.util.Map; import java.util.Set; - import javax.xml.namespace.QName; -import org.w3c.dom.Element; - import com.github.sardine.report.SardineReport; +import org.w3c.dom.Element; /** * The main interface for Sardine operations. @@ -27,16 +25,34 @@ public interface Sardine * @param username Use in authentication header credentials * @param password Use in authentication header credentials */ + @Deprecated void setCredentials(String username, String password); + /** + * Add credentials to any scope. + * + * @param username Use in authentication header credentials + * @param password Use in authentication header credentials + */ + void setCredentials(String username, char[] password); + /** * @param username Use in authentication header credentials * @param password Use in authentication header credentials * @param domain NTLM authentication * @param workstation NTLM authentication */ + @Deprecated void setCredentials(String username, String password, String domain, String workstation); + /** + * @param username Use in authentication header credentials + * @param password Use in authentication header credentials + * @param domain NTLM authentication + * @param workstation NTLM authentication + */ + void setCredentials(String username, char[] password, String domain, String workstation); + /** * @see #list(String) */ @@ -305,10 +321,11 @@ public interface Sardine * * @param url Path to the resource including protocol and hostname (must not point to a directory) * @param dataStream Input source + * @param contentType MIME type to add to the HTTP request header * @param headers Additional HTTP headers to add to the request * @throws IOException I/O error or HTTP response validation failure */ - void put(String url, InputStream dataStream, Map headers) throws IOException; + void put(String url, InputStream dataStream, String contentType, Map headers) throws IOException; /** * Uses PUT to upload file to a server with specific contentType. @@ -548,6 +565,8 @@ public interface Sardine */ List getPrincipalCollectionSet(String url) throws IOException; + void enableHttp2(); + /** *

* Enables HTTP GZIP compression. If enabled, requests originating from Sardine diff --git a/src/main/java/com/github/sardine/SardineFactory.java b/src/main/java/com/github/sardine/SardineFactory.java index 1e3de83f..f4969c59 100644 --- a/src/main/java/com/github/sardine/SardineFactory.java +++ b/src/main/java/com/github/sardine/SardineFactory.java @@ -41,6 +41,6 @@ public static Sardine begin(String username, String password) */ public static Sardine begin(String username, String password, ProxySelector proxy) { - return new SardineImpl(username, password, proxy); + return new SardineImpl(username, password != null ? password.toCharArray() : null, proxy); } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/sardine/ant/SardineTask.java b/src/main/java/com/github/sardine/ant/SardineTask.java index fb3b578d..390cd8f6 100644 --- a/src/main/java/com/github/sardine/ant/SardineTask.java +++ b/src/main/java/com/github/sardine/ant/SardineTask.java @@ -101,7 +101,7 @@ public void execute() throws BuildException { sardine = SardineFactory.begin(username, password); } else { sardine = SardineFactory.begin(); - sardine.setCredentials(username, password, domain, workstation); + sardine.setCredentials(username, password.toCharArray(), domain, workstation); } if (ignoreCookies) { diff --git a/src/main/java/com/github/sardine/impl/SardineException.java b/src/main/java/com/github/sardine/impl/SardineException.java index 7d14f905..c0256cc1 100644 --- a/src/main/java/com/github/sardine/impl/SardineException.java +++ b/src/main/java/com/github/sardine/impl/SardineException.java @@ -16,7 +16,8 @@ package com.github.sardine.impl; -import org.apache.http.client.HttpResponseException; + +import org.apache.hc.client5.http.HttpResponseException; /** * Specialized type of exception for Sardine so @@ -56,4 +57,4 @@ public String getMessage() { return String.format("%s (%d %s)", super.getMessage(), this.getStatusCode(), this.getResponsePhrase()); } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/sardine/impl/SardineImpl.java b/src/main/java/com/github/sardine/impl/SardineImpl.java index 95a34d4f..a28659db 100644 --- a/src/main/java/com/github/sardine/impl/SardineImpl.java +++ b/src/main/java/com/github/sardine/impl/SardineImpl.java @@ -28,46 +28,44 @@ import com.github.sardine.report.SardineReport; import com.github.sardine.report.VersionTreeReport; import com.github.sardine.util.SardineUtil; -import org.apache.http.*; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.AuthState; -import org.apache.http.auth.NTCredentials; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.AuthCache; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.HttpResponseException; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.config.AuthSchemes; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.*; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.client.protocol.RequestAcceptEncoding; -import org.apache.http.client.protocol.ResponseContentEncoding; -import org.apache.http.config.Lookup; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.conn.SchemePortResolver; -import org.apache.http.conn.routing.HttpRoutePlanner; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.cookie.CookieSpecProvider; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.FileEntity; -import org.apache.http.entity.InputStreamEntity; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.auth.BasicScheme; -import org.apache.http.impl.client.*; -import org.apache.http.impl.conn.DefaultSchemePortResolver; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.http.impl.conn.SystemDefaultRoutePlanner; -import org.apache.http.impl.cookie.IgnoreSpecProvider; -import org.apache.http.message.BasicHeader; -import org.apache.http.protocol.BasicHttpContext; -import org.apache.http.protocol.HTTP; -import org.apache.http.protocol.HttpContext; -import org.apache.http.util.VersionInfo; +import org.apache.hc.client5.http.HttpResponseException; +import org.apache.hc.client5.http.SchemePortResolver; +import org.apache.hc.client5.http.auth.*; +import org.apache.hc.client5.http.classic.methods.*; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.cookie.CookieSpecFactory; +import org.apache.hc.client5.http.entity.GzipDecompressingEntity; +import org.apache.hc.client5.http.impl.DefaultRedirectStrategy; +import org.apache.hc.client5.http.impl.DefaultSchemePortResolver; +import org.apache.hc.client5.http.impl.auth.BasicAuthCache; +import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; +import org.apache.hc.client5.http.impl.auth.BasicScheme; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.cookie.IgnoreCookieSpecFactory; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.routing.SystemDefaultRoutePlanner; +import org.apache.hc.client5.http.io.HttpClientConnectionManager; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.client5.http.protocol.RedirectStrategy; +import org.apache.hc.client5.http.routing.HttpRoutePlanner; +import org.apache.hc.client5.http.socket.ConnectionSocketFactory; +import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.core5.http.*; +import org.apache.hc.core5.http.config.Lookup; +import org.apache.hc.core5.http.config.Registry; +import org.apache.hc.core5.http.config.RegistryBuilder; +import org.apache.hc.core5.http.io.HttpClientResponseHandler; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.io.entity.FileEntity; +import org.apache.hc.core5.http.io.entity.InputStreamEntity; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.hc.core5.http.protocol.BasicHttpContext; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.util.VersionInfo; import org.w3c.dom.Element; import javax.xml.namespace.QName; @@ -77,7 +75,7 @@ import java.net.ProxySelector; import java.net.URISyntaxException; import java.net.URL; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -96,7 +94,16 @@ public class SardineImpl implements Sardine { private static final Logger log = Logger.getLogger(DavResource.class.getName()); - private static final String UTF_8 = "UTF-8"; + /** + * Value for "Expect" HTTP header + */ + private static final String EXPECT_CONTINUE = "100-Continue"; + + /** + * Default content charset originally used by v4 of HTTP client. + */ + private static final String DEF_CONTENT_CHARSET = StandardCharsets.ISO_8859_1.name(); + private static final String HTTP_MAJOR_VERSION = "HTTP_MAJOR_VERSION"; /** * HTTP client implementation @@ -128,7 +135,7 @@ public SardineImpl() */ public SardineImpl(String bearerAuth) { - Header bearerHeader = new BasicHeader("Authorization", "Bearer " + bearerAuth); + Header bearerHeader = new BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + bearerAuth); this.builder = this.configure(null, null).setDefaultHeaders(Collections.singletonList(bearerHeader)); this.client = this.builder.build(); } @@ -139,7 +146,7 @@ public SardineImpl(String bearerAuth) * @param username Use in authentication header credentials * @param password Use in authentication header credentials */ - public SardineImpl(String username, String password) + public SardineImpl(String username, char[] password) { this.builder = this.configure(null, this.createDefaultCredentialsProvider(username, password, null, null)); this.client = this.builder.build(); @@ -150,7 +157,7 @@ public SardineImpl(String username, String password) * @param password Use in authentication header credentials * @param selector Proxy configuration */ - public SardineImpl(String username, String password, ProxySelector selector) + public SardineImpl(String username, char[] password, ProxySelector selector) { this.builder = this.configure(selector, this.createDefaultCredentialsProvider(username, password, null, null)); this.client = this.builder.build(); @@ -170,13 +177,18 @@ public SardineImpl(HttpClientBuilder builder) * @param username Use in authentication header credentials * @param password Use in authentication header credentials */ - public SardineImpl(HttpClientBuilder builder, String username, String password) + public SardineImpl(HttpClientBuilder builder, String username, char[] password) { this.builder = builder; this.setCredentials(username, password); this.client = this.builder.build(); } + @Override + public void setCredentials(String username, String password) { + this.setCredentials(username, password.toCharArray()); + } + /** * Add credentials to any scope. Supports Basic, Digest and NTLM authentication methods. * @@ -184,11 +196,16 @@ public SardineImpl(HttpClientBuilder builder, String username, String password) * @param password Use in authentication header credentials */ @Override - public void setCredentials(String username, String password) + public void setCredentials(String username, char[] password) { this.setCredentials(username, password, "", ""); } + @Override + public void setCredentials(String username, String password, String domain, String workstation) { + this.setCredentials(username, password.toCharArray(), domain, workstation); + } + /** * @param username Use in authentication header credentials * @param password Use in authentication header credentials @@ -196,7 +213,7 @@ public void setCredentials(String username, String password) * @param workstation NTLM authentication */ @Override - public void setCredentials(String username, String password, String domain, String workstation) + public void setCredentials(String username, char[] password, String domain, String workstation) { this.setCredentials(this.createDefaultCredentialsProvider(username, password, domain, workstation)); } @@ -204,28 +221,27 @@ public void setCredentials(String username, String password, String domain, Stri public void setCredentials(CredentialsProvider provider) { this.context.setCredentialsProvider(provider); - this.context.setAttribute(HttpClientContext.TARGET_AUTH_STATE, new AuthState()); } - private CredentialsProvider createDefaultCredentialsProvider(String username, String password, String domain, String workstation) + private CredentialsProvider createDefaultCredentialsProvider(String username, char[] password, String domain, String workstation) { - CredentialsProvider provider = new BasicCredentialsProvider(); + CredentialsStore provider = new BasicCredentialsProvider(); if (username != null) { provider.setCredentials( - new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.NTLM), + new AuthScope(null, null, -1, null, StandardAuthScheme.NTLM), new NTCredentials(username, password, workstation, domain)); provider.setCredentials( - new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.BASIC), + new AuthScope(null, null, -1, null, StandardAuthScheme.BASIC), new UsernamePasswordCredentials(username, password)); provider.setCredentials( - new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.DIGEST), + new AuthScope(null, null, -1, null, StandardAuthScheme.DIGEST), new UsernamePasswordCredentials(username, password)); provider.setCredentials( - new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.SPNEGO), + new AuthScope(null, null, -1, null, StandardAuthScheme.SPNEGO), new NTCredentials(username, password, workstation, domain)); provider.setCredentials( - new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.KERBEROS), + new AuthScope(null, null, -1, null, StandardAuthScheme.KERBEROS), new UsernamePasswordCredentials(username, password)); } return provider; @@ -237,8 +253,23 @@ private CredentialsProvider createDefaultCredentialsProvider(String username, St @Override public void enableCompression() { - this.builder.addInterceptorLast(new RequestAcceptEncoding()); - this.builder.addInterceptorLast(new ResponseContentEncoding()); + // Adding content encoding (gzip) support + this.builder.addRequestInterceptorLast((httpRequest, entityDetails, context) -> { + httpRequest.addHeader("Accept-Encoding", "gzip"); + }); + + this.builder.addResponseInterceptorLast((httpResponse, entityDetails, context) -> { + ClassicHttpResponse classicHttpResponse = (ClassicHttpResponse) httpResponse; + HttpEntity entity = classicHttpResponse.getEntity(); + + if (httpResponse.containsHeader("Content-Encoding") && + "gzip".equalsIgnoreCase(httpResponse.getHeader("Content-Encoding").getValue())) { + // Decompressing the gzip content + ClassicHttpResponse.class.cast(httpResponse).setEntity( + new GzipDecompressingEntity(entity)); + } + }); + this.client = this.builder.build(); } @@ -258,14 +289,7 @@ public void disableCompression() @Override public void ignoreCookies() { - this.builder.setDefaultCookieSpecRegistry(new Lookup() - { - @Override - public CookieSpecProvider lookup(String name) - { - return new IgnoreSpecProvider(); - } - }); + this.builder.setDefaultCookieSpecRegistry(name -> new IgnoreCookieSpecFactory()); this.client = this.builder.build(); } @@ -303,30 +327,25 @@ else if ("http".equals(protocol)) @Override public void enablePreemptiveAuthentication(String hostname, int httpPort, int httpsPort) { - enablePreemptiveAuthentication(hostname, httpPort, httpsPort, Consts.ISO_8859_1); - } - - public void enablePreemptiveAuthentication(String hostname, int httpPort, int httpsPort, Charset credentialsCharset) - { - AuthCache cache = this.context.getAuthCache(); + AuthCache cache = context.getAuthCache(); if (cache == null) { // Add AuthCache to the execution context cache = new BasicAuthCache(); - this.context.setAuthCache(cache); + context.setAuthCache(cache); } // Generate Basic preemptive scheme object and stick it to the local execution context - BasicScheme basicAuth = new BasicScheme(credentialsCharset); + BasicScheme basicAuth = new BasicScheme(); // Configure HttpClient to authenticate preemptively by prepopulating the authentication data cache. - cache.put(new HttpHost(hostname, httpPort == -1 ? 80 : httpPort, "http"), basicAuth); - cache.put(new HttpHost(hostname, httpsPort == -1 ? 443 : httpsPort, "https"), basicAuth); + cache.put(new HttpHost("http", hostname, httpPort), basicAuth); + cache.put(new HttpHost("https", hostname, httpsPort), basicAuth); } @Override public void disablePreemptiveAuthentication() { - this.context.removeAttribute(HttpClientContext.AUTH_CACHE); + context.setAuthCache(null); } @Override @@ -358,7 +377,7 @@ public List list(String url, int depth, boolean allProp) throws IOE } else { - return list(url, depth, Collections.emptySet()); + return list(url, depth, Collections.emptySet()); } } @@ -369,7 +388,7 @@ public List versionsList(String url) throws IOException { @Override public List versionsList(String url, int depth) throws IOException { - return versionsList(url, depth, Collections.emptySet()); + return versionsList(url, depth, Collections.emptySet()); } @Override @@ -420,10 +439,10 @@ protected List propfind(String url, int depth, Propfind body) throw { HttpPropFind entity = new HttpPropFind(url); entity.setDepth(depth < 0 ? "infinity" : Integer.toString(depth)); - entity.setEntity(new StringEntity(SardineUtil.toXml(body), UTF_8)); + entity.setEntity(new StringEntity(SardineUtil.toXml(body), StandardCharsets.UTF_8)); Multistatus multistatus = this.execute(entity, new MultiStatusResponseHandler()); List responses = multistatus.getResponse(); - List resources = new ArrayList(responses.size()); + List resources = new ArrayList<>(responses.size()); for (Response response : responses) { try @@ -442,20 +461,20 @@ public T report(String url, int depth, SardineReport report) throws IOExc { HttpReport entity = new HttpReport(url); entity.setDepth(depth < 0 ? "infinity" : Integer.toString(depth)); - entity.setEntity(new StringEntity(report.toXml(), UTF_8)); + entity.setEntity(new StringEntity(report.toXml(), StandardCharsets.UTF_8)); Multistatus multistatus = this.execute(entity, new MultiStatusResponseHandler()); return report.fromMultistatus(multistatus); } public List search(String url, String language, String query) throws IOException { - HttpEntityEnclosingRequestBase search = new HttpSearch(url); + HttpSearch search = new HttpSearch(url); SearchRequest searchBody = new SearchRequest(language, query); String body = SardineUtil.toXml(searchBody); - search.setEntity(new StringEntity(body, UTF_8)); + search.setEntity(createEntity(body)); Multistatus multistatus = this.execute(search, new MultiStatusResponseHandler()); List responses = multistatus.getResponse(); - List resources = new ArrayList(responses.size()); + List resources = new ArrayList<>(responses.size()); for (Response response : responses) { try @@ -479,7 +498,7 @@ public void setCustomProps(String url, Map set, List rem @Override public List patch(String url, Map setProps) throws IOException { - return this.patch(url, setProps, Collections.emptyList()); + return this.patch(url, setProps, Collections.emptyList()); } /** @@ -490,7 +509,7 @@ public List patch(String url, Map setProps) throws I @Override public List patch(String url, Map setProps, List removeProps) throws IOException { - List setPropsElements = new ArrayList(); + List setPropsElements = new ArrayList<>(); for (Entry entry : setProps.entrySet()) { Element element = SardineUtil.createElement(entry.getKey()); @@ -508,7 +527,7 @@ public List patch(String url, Map setProps, List patch(String url, List setProps, List removeProps) throws IOException { - return this.patch(url, setProps, removeProps, Collections.emptyMap()); + return this.patch(url, setProps, removeProps, Collections.emptyMap()); } @Override @@ -519,6 +538,7 @@ public List patch(String url, List setProps, List r { patch.addHeader(new BasicHeader(h.getKey(), h.getValue())); } + HttpPropPatch entity = new HttpPropPatch(url); // Build WebDAV PROPPATCH entity. Propertyupdate body = new Propertyupdate(); // Add properties @@ -550,10 +570,10 @@ public List patch(String url, List setProps, List r remove.setProp(prop); } } - patch.setEntity(new StringEntity(SardineUtil.toXml(body), UTF_8)); - Multistatus multistatus = this.execute(patch, new MultiStatusResponseHandler()); + entity.setEntity(createEntity(body)); + Multistatus multistatus = this.execute(entity, new MultiStatusResponseHandler()); List responses = multistatus.getResponse(); - List resources = new ArrayList(responses.size()); + List resources = new ArrayList<>(responses.size()); for (Response response : responses) { try @@ -579,7 +599,7 @@ public String lock(String url) throws IOException Locktype lockType = new Locktype(); lockType.setWrite(new Write()); body.setLocktype(lockType); - entity.setEntity(new StringEntity(SardineUtil.toXml(body), UTF_8)); + entity.setEntity(createEntity(body)); // Return the lock token return this.execute(entity, new LockResponseHandler()); } @@ -596,13 +616,6 @@ public String refreshLock(String url, String token, String file) throws IOExcept public void unlock(String url, String token) throws IOException { HttpUnlock entity = new HttpUnlock(url, token); - Lockinfo body = new Lockinfo(); - Lockscope scopeType = new Lockscope(); - scopeType.setExclusive(new Exclusive()); - body.setLockscope(scopeType); - Locktype lockType = new Locktype(); - lockType.setWrite(new Write()); - body.setLocktype(lockType); this.execute(entity, new VoidResponseHandler()); } @@ -627,7 +640,7 @@ public void setAcl(String url, List aces) throws IOException HttpAcl entity = new HttpAcl(url); // Build WebDAV ACL entity. Acl body = new Acl(); - body.setAce(new ArrayList()); + body.setAce(new ArrayList<>()); for (DavAce davAce : aces) { // protected and inherited acl must not be part of ACL http request @@ -638,7 +651,7 @@ public void setAcl(String url, List aces) throws IOException Ace ace = davAce.toModel(); body.getAce().add(ace); } - entity.setEntity(new StringEntity(SardineUtil.toXml(body), UTF_8)); + entity.setEntity(createEntity(body)); this.execute(entity, new VoidResponseHandler()); } @@ -654,7 +667,7 @@ public DavAcl getAcl(String url) throws IOException prop.setGroup(new Group()); prop.setAcl(new Acl()); body.setProp(prop); - entity.setEntity(new StringEntity(SardineUtil.toXml(body), UTF_8)); + entity.setEntity(createEntity(body)); Multistatus multistatus = this.execute(entity, new MultiStatusResponseHandler()); List responses = multistatus.getResponse(); if (responses.isEmpty()) @@ -677,7 +690,7 @@ public DavQuota getQuota(String url) throws IOException prop.setQuotaAvailableBytes(new QuotaAvailableBytes()); prop.setQuotaUsedBytes(new QuotaUsedBytes()); body.setProp(prop); - entity.setEntity(new StringEntity(SardineUtil.toXml(body), UTF_8)); + entity.setEntity(createEntity(body)); Multistatus multistatus = this.execute(entity, new MultiStatusResponseHandler()); List responses = multistatus.getResponse(); if (responses.isEmpty()) @@ -709,7 +722,7 @@ public List getPrincipals(String url) throws IOException prop.setResourcetype(new Resourcetype()); prop.setPrincipalURL(new PrincipalURL()); body.setProp(prop); - entity.setEntity(new StringEntity(SardineUtil.toXml(body), UTF_8)); + entity.setEntity(createEntity(body)); Multistatus multistatus = this.execute(entity, new MultiStatusResponseHandler()); List responses = multistatus.getResponse(); if (responses.isEmpty()) @@ -718,7 +731,7 @@ public List getPrincipals(String url) throws IOException } else { - List collections = new ArrayList(); + List collections = new ArrayList<>(); for (Response r : responses) { if (r.getPropstat() != null) @@ -749,7 +762,7 @@ public List getPrincipalCollectionSet(String url) throws IOException Prop prop = new Prop(); prop.setPrincipalCollectionSet(new PrincipalCollectionSet()); body.setProp(prop); - entity.setEntity(new StringEntity(SardineUtil.toXml(body), UTF_8)); + entity.setEntity(createEntity(body)); Multistatus multistatus = this.execute(entity, new MultiStatusResponseHandler()); List responses = multistatus.getResponse(); if (responses.isEmpty()) @@ -758,7 +771,7 @@ public List getPrincipalCollectionSet(String url) throws IOException } else { - List collections = new ArrayList(); + List collections = new ArrayList<>(); for (Response r : responses) { if (r.getPropstat() != null) @@ -778,10 +791,15 @@ public List getPrincipalCollectionSet(String url) throws IOException } } + @Override + public void enableHttp2() { + context.setAttribute(HTTP_MAJOR_VERSION, 2); + } + @Override public ContentLengthInputStream get(String url) throws IOException { - return this.get(url, Collections.emptyMap()); + return this.get(url, Collections.emptyMap()); } @Override @@ -794,7 +812,7 @@ public ContentLengthInputStream get(String url, String version) throws IOExcepti @Override public ContentLengthInputStream get(String url, Map headers) throws IOException { - List

list = new ArrayList
(); + List
list = new ArrayList<>(); for (Map.Entry h : headers.entrySet()) { list.add(new BasicHeader(h.getKey(), h.getValue())); @@ -811,7 +829,7 @@ public ContentLengthInputStream get(String url, List
headers) throws IOE } // Must use #execute without handler, otherwise the entity is consumed // already after the handler exits. - HttpResponse response = this.execute(get); + ClassicHttpResponse response = this.execute(get); VoidResponseHandler handler = new VoidResponseHandler(); try { @@ -835,14 +853,14 @@ public void put(String url, byte[] data) throws IOException @Override public void put(String url, byte[] data, String contentType) throws IOException { - ByteArrayEntity entity = new ByteArrayEntity(data); + ByteArrayEntity entity = new ByteArrayEntity(data, createContentType(contentType)); this.put(url, entity, contentType, true); } @Override public void put(String url, InputStream dataStream) throws IOException { - this.put(url, dataStream, (String) null); + this.put(url, dataStream, null); } @Override @@ -861,25 +879,25 @@ public void put(String url, InputStream dataStream, String contentType, boolean @Override public void put(String url, InputStream dataStream, String contentType, boolean expectContinue, long contentLength) throws IOException { - InputStreamEntity entity = new InputStreamEntity(dataStream, contentLength); + InputStreamEntity entity = new InputStreamEntity(dataStream, contentLength, createContentType(contentType)); this.put(url, entity, contentType, expectContinue); } @Override - public void put(String url, InputStream dataStream, Map headers) throws IOException + public void put(String url, InputStream dataStream, String contentType, Map headers) throws IOException { - List
list = new ArrayList
(); + List
list = new ArrayList<>(); for (Map.Entry h : headers.entrySet()) { list.add(new BasicHeader(h.getKey(), h.getValue())); } - this.put(url, dataStream, list); + this.put(url, dataStream, contentType, list); } - public void put(String url, InputStream dataStream, List
headers) throws IOException + public void put(String url, InputStream dataStream, String contentType, List
headers) throws IOException { // A length of -1 means "go until end of stream" - InputStreamEntity entity = new InputStreamEntity(dataStream, -1); + InputStreamEntity entity = new InputStreamEntity(dataStream, -1, createContentType(contentType)); this.put(url, entity, headers); } @@ -893,14 +911,14 @@ public void put(String url, InputStream dataStream, List
headers) throws */ public void put(String url, HttpEntity entity, String contentType, boolean expectContinue) throws IOException { - List
headers = new ArrayList
(); + List
headers = new ArrayList<>(); if (contentType != null) { headers.add(new BasicHeader(HttpHeaders.CONTENT_TYPE, contentType)); } if (expectContinue) { - headers.add(new BasicHeader(HTTP.EXPECT_DIRECTIVE, HTTP.EXPECT_CONTINUE)); + headers.add(new BasicHeader(HttpHeaders.EXPECT, EXPECT_CONTINUE)); } this.put(url, entity, headers); } @@ -917,7 +935,7 @@ public void put(String url, HttpEntity entity, List
headers) throws IOEx this.put(url, entity, headers, new VoidResponseHandler()); } - public T put(String url, HttpEntity entity, List
headers, ResponseHandler handler) throws IOException + public T put(String url, HttpEntity entity, List
headers, HttpClientResponseHandler handler) throws IOException { HttpPut put = new HttpPut(url); put.setEntity(entity); @@ -927,7 +945,7 @@ public T put(String url, HttpEntity entity, List
headers, ResponseHa } if (entity.getContentType() == null && !put.containsHeader(HttpHeaders.CONTENT_TYPE)) { - put.addHeader(HttpHeaders.CONTENT_TYPE, HTTP.DEF_CONTENT_CHARSET.name()); + put.addHeader(HttpHeaders.CONTENT_TYPE, DEF_CONTENT_CHARSET); } try { @@ -938,7 +956,7 @@ public T put(String url, HttpEntity entity, List
headers, ResponseHa if (e.getStatusCode() == HttpStatus.SC_EXPECTATION_FAILED) { // Retry with the Expect header removed - put.removeHeaders(HTTP.EXPECT_DIRECTIVE); + put.removeHeaders(HttpHeaders.EXPECT); if (entity.isRepeatable()) { return this.execute(put, handler); @@ -951,21 +969,21 @@ public T put(String url, HttpEntity entity, List
headers, ResponseHa @Override public void put(String url, File localFile, String contentType) throws IOException { - //don't use ExpectContinue for repetable FileEntity, some web server (IIS for exmaple) may return 400 bad request after retry - this.put(url, localFile, contentType, false); + //don't use ExpectContinue for repeatable FileEntity, some web server (IIS for example) may return 400 bad request after retry + put(url, localFile, contentType, false); } @Override public void put(String url, File localFile, String contentType, boolean expectContinue) throws IOException { - FileEntity content = new FileEntity(localFile); + FileEntity content = new FileEntity(localFile, createContentType(contentType)); this.put(url, content, contentType, expectContinue); } @Override public void delete(String url) throws IOException { - this.delete(url, Collections.emptyMap()); + this.delete(url, Collections.emptyMap()); } @Override @@ -984,7 +1002,7 @@ public void move(String sourceUrl, String destinationUrl) throws IOException @Override public void move(String sourceUrl, String destinationUrl, boolean overwrite) throws IOException { - this.move(sourceUrl, destinationUrl, overwrite, Collections.emptyMap()); + this.move(sourceUrl, destinationUrl, overwrite, Collections.emptyMap()); } @Override @@ -1001,13 +1019,13 @@ public void move(String sourceUrl, String destinationUrl, boolean overwrite, Map @Override public void copy(String sourceUrl, String destinationUrl) throws IOException { - this.copy(sourceUrl, destinationUrl, true); + copy(sourceUrl, destinationUrl, true); } @Override public void copy(String sourceUrl, String destinationUrl, boolean overwrite) throws IOException { - this.copy(sourceUrl, destinationUrl, overwrite, Collections.emptyMap()); + this.copy(sourceUrl, destinationUrl, overwrite, Collections.emptyMap()); } @Override @@ -1043,7 +1061,7 @@ public boolean exists(String url) throws IOException * @param responseHandler Determines the return type. * @return parsed response */ - protected T execute(HttpRequestBase request, ResponseHandler responseHandler) + protected T execute(HttpUriRequestBase request, HttpClientResponseHandler responseHandler) throws IOException { return execute(context, request, responseHandler); @@ -1055,7 +1073,7 @@ protected T execute(HttpRequestBase request, ResponseHandler responseHand * @param request Request to execute * @return The response to check the reply status code */ - protected HttpResponse execute(HttpRequestBase request) + protected ClassicHttpResponse execute(HttpUriRequestBase request) throws IOException { return execute(context, request, null); @@ -1069,15 +1087,20 @@ protected HttpResponse execute(HttpRequestBase request) * @param will return raw HttpResponse when responseHandler is null or value reslved using provided ResponseHandler instance * @return value resolved using response handler or raw HttpResponse when responseHandler is null */ - protected T execute(HttpClientContext context, HttpRequestBase request, ResponseHandler responseHandler) + protected T execute(HttpClientContext context, HttpUriRequestBase request, HttpClientResponseHandler responseHandler) throws IOException { - HttpContext requestLocalContext = new BasicHttpContext(context); + Integer httpMajorVersion = (Integer) context.getAttribute(HTTP_MAJOR_VERSION); + + if (httpMajorVersion != null){ + request.setVersion(new ProtocolVersion("HTTP", httpMajorVersion, 0)); + } + HttpClientContext requestLocalContext = new HttpClientContext(context); try { if (responseHandler != null) { - return this.client.execute(request, responseHandler, requestLocalContext); + return this.client.execute(request, requestLocalContext, responseHandler); } else { @@ -1096,7 +1119,7 @@ protected T execute(HttpClientContext context, HttpRequestBase request, Resp } finally { - context.setAttribute(HttpClientContext.USER_TOKEN, requestLocalContext.getAttribute(HttpClientContext.USER_TOKEN)); + context.setUserToken(requestLocalContext.getUserToken()); } } @@ -1137,9 +1160,9 @@ protected DefaultSchemePortResolver createDefaultSchemePortResolver() return new DefaultSchemePortResolver(); } - protected SardineRedirectStrategy createDefaultRedirectStrategy() + protected RedirectStrategy createDefaultRedirectStrategy() { - return new SardineRedirectStrategy(); + return new DefaultRedirectStrategy(); } /** @@ -1191,4 +1214,26 @@ protected HttpRoutePlanner createDefaultRoutePlanner(SchemePortResolver resolver { return new SystemDefaultRoutePlanner(resolver, selector); } + + /** + * Common logic to create an HTTP entity for a JAXB element. + * + * @param jaxbElement the JAXB element. + * @return the HTTP entity. + * @throws IOException if an error occurs serialising the element. + */ + private static HttpEntity createEntity(Object jaxbElement) throws IOException + { + return new StringEntity(SardineUtil.toXml(jaxbElement), StandardCharsets.UTF_8); + } + + /** + * Create MIME content type from string + * + * @param contentType MIME content type or null + * @return May be null + */ + private static ContentType createContentType(String contentType) { + return contentType != null ? ContentType.create(contentType) : null; + } } diff --git a/src/main/java/com/github/sardine/impl/SardineRedirectStrategy.java b/src/main/java/com/github/sardine/impl/SardineRedirectStrategy.java deleted file mode 100644 index 023b6220..00000000 --- a/src/main/java/com/github/sardine/impl/SardineRedirectStrategy.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2009-2011 Jon Stevens et al. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.github.sardine.impl; - -import org.apache.http.Header; -import org.apache.http.HttpEntityEnclosingRequest; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.ProtocolException; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.impl.client.DefaultRedirectStrategy; -import org.apache.http.protocol.HttpContext; - -import com.github.sardine.impl.methods.HttpPropFind; -import com.github.sardine.impl.methods.HttpReport; - -public class SardineRedirectStrategy extends DefaultRedirectStrategy { - - @Override - protected boolean isRedirectable(String method) { - if (super.isRedirectable(method)) - { - return true; - } - return method.equalsIgnoreCase(HttpPropFind.METHOD_NAME); - } - - @Override - public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, HttpContext context) - throws ProtocolException - { - String method = request.getRequestLine().getMethod(); - if (method.equalsIgnoreCase(HttpPropFind.METHOD_NAME)) - { - HttpPropFind propfind = new HttpPropFind(this.getLocationURI(request, response, context)); - Header depth = request.getFirstHeader("Depth"); - if (depth != null && depth.getValue() != null) - { - propfind.setDepth(depth.getValue()); - } - return this.copyEntity(propfind, request); - } - else if (method.equalsIgnoreCase(HttpReport.METHOD_NAME)) - { - HttpReport report = new HttpReport(this.getLocationURI(request, response, context)); - Header depth = request.getFirstHeader("Depth"); - if (depth != null && depth.getValue() != null) - { - report.setDepth(depth.getValue()); - } - return this.copyEntity(report, request); - } - return super.getRedirect(request, response, context); - } - - private HttpUriRequest copyEntity(final HttpEntityEnclosingRequestBase redirect, final HttpRequest original) { - if (original instanceof HttpEntityEnclosingRequest) - { - redirect.setEntity(((HttpEntityEnclosingRequest) original).getEntity()); - } - return redirect; - } -} diff --git a/src/main/java/com/github/sardine/impl/handler/ETagResponseHandler.java b/src/main/java/com/github/sardine/impl/handler/ETagResponseHandler.java index 5c1d89f6..23396149 100644 --- a/src/main/java/com/github/sardine/impl/handler/ETagResponseHandler.java +++ b/src/main/java/com/github/sardine/impl/handler/ETagResponseHandler.java @@ -18,12 +18,13 @@ import java.io.IOException; -import org.apache.http.HttpHeaders; -import org.apache.http.HttpResponse; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpHeaders; + public class ETagResponseHandler extends ValidatingResponseHandler { @Override - public String handleResponse(HttpResponse response) throws IOException { + public String handleResponse(ClassicHttpResponse response) throws IOException { this.validateResponse(response); if(response.containsHeader(HttpHeaders.ETAG)) { return response.getFirstHeader(HttpHeaders.ETAG).getValue(); diff --git a/src/main/java/com/github/sardine/impl/handler/ExistsResponseHandler.java b/src/main/java/com/github/sardine/impl/handler/ExistsResponseHandler.java index df6dfca1..b06e81ac 100644 --- a/src/main/java/com/github/sardine/impl/handler/ExistsResponseHandler.java +++ b/src/main/java/com/github/sardine/impl/handler/ExistsResponseHandler.java @@ -16,23 +16,24 @@ package com.github.sardine.impl.handler; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; + +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.message.StatusLine; import com.github.sardine.impl.SardineException; /** - * {@link org.apache.http.client.ResponseHandler} which checks whether a given resource exists. + * {@link org.apache.hc.core5.http.io.HttpClientResponseHandler} which checks whether a given resource exists. * * @author mirko */ public class ExistsResponseHandler extends ValidatingResponseHandler { @Override - public Boolean handleResponse(HttpResponse response) throws SardineException + public Boolean handleResponse(ClassicHttpResponse response) throws SardineException { - StatusLine statusLine = response.getStatusLine(); + StatusLine statusLine = new StatusLine(response); int statusCode = statusLine.getStatusCode(); if (statusCode < HttpStatus.SC_MULTIPLE_CHOICES) { diff --git a/src/main/java/com/github/sardine/impl/handler/HeadersResponseHandler.java b/src/main/java/com/github/sardine/impl/handler/HeadersResponseHandler.java index 13a841e0..051add32 100644 --- a/src/main/java/com/github/sardine/impl/handler/HeadersResponseHandler.java +++ b/src/main/java/com/github/sardine/impl/handler/HeadersResponseHandler.java @@ -20,15 +20,16 @@ import java.util.HashMap; import java.util.Map; -import org.apache.http.Header; -import org.apache.http.HttpResponse; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.Header; + public class HeadersResponseHandler extends ValidatingResponseHandler> { @Override - public Map handleResponse(HttpResponse response) throws IOException { + public Map handleResponse(ClassicHttpResponse response) throws IOException { this.validateResponse(response); Map headers = new HashMap(); - for(Header h : response.getAllHeaders()) { + for(Header h : response.getHeaders()) { headers.put(h.getName(), h.getValue()); } return headers; diff --git a/src/main/java/com/github/sardine/impl/handler/LockResponseHandler.java b/src/main/java/com/github/sardine/impl/handler/LockResponseHandler.java index e55f3587..08a5c2c9 100644 --- a/src/main/java/com/github/sardine/impl/handler/LockResponseHandler.java +++ b/src/main/java/com/github/sardine/impl/handler/LockResponseHandler.java @@ -19,9 +19,10 @@ import java.io.IOException; import java.io.InputStream; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; + +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.message.StatusLine; import com.github.sardine.impl.SardineException; import com.github.sardine.model.Prop; @@ -32,13 +33,13 @@ public class LockResponseHandler extends ValidatingResponseHandler { @Override - public String handleResponse(HttpResponse response) throws IOException + public String handleResponse(ClassicHttpResponse response) throws IOException { super.validateResponse(response); // Process the response from the server. HttpEntity entity = response.getEntity(); - StatusLine statusLine = response.getStatusLine(); + StatusLine statusLine = new StatusLine(response); if (entity == null) { throw new SardineException("No entity found in response", statusLine.getStatusCode(), diff --git a/src/main/java/com/github/sardine/impl/handler/MultiStatusResponseHandler.java b/src/main/java/com/github/sardine/impl/handler/MultiStatusResponseHandler.java index 87eefac5..40412a70 100644 --- a/src/main/java/com/github/sardine/impl/handler/MultiStatusResponseHandler.java +++ b/src/main/java/com/github/sardine/impl/handler/MultiStatusResponseHandler.java @@ -19,16 +19,16 @@ import java.io.IOException; import java.io.InputStream; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.message.StatusLine; import com.github.sardine.impl.SardineException; import com.github.sardine.model.Multistatus; import com.github.sardine.util.SardineUtil; /** - * {@link org.apache.http.client.ResponseHandler} which returns the {@link Multistatus} response of + * {@link org.apache.hc.core5.http.io.HttpClientResponseHandler} which returns the {@link Multistatus} response of * a {@link com.github.sardine.impl.methods.HttpPropFind} request. * * @author mirko @@ -36,13 +36,13 @@ public class MultiStatusResponseHandler extends ValidatingResponseHandler { @Override - public Multistatus handleResponse(HttpResponse response) throws IOException + public Multistatus handleResponse(ClassicHttpResponse response) throws IOException { super.validateResponse(response); // Process the response from the server. HttpEntity entity = response.getEntity(); - StatusLine statusLine = response.getStatusLine(); + StatusLine statusLine = new StatusLine(response); if (entity == null) { throw new SardineException("No entity found in response", statusLine.getStatusCode(), @@ -70,4 +70,4 @@ protected Multistatus getMultistatus(InputStream stream) { return SardineUtil.unmarshal(stream); } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/sardine/impl/handler/ValidatingResponseHandler.java b/src/main/java/com/github/sardine/impl/handler/ValidatingResponseHandler.java index b1b53660..be4c07a3 100644 --- a/src/main/java/com/github/sardine/impl/handler/ValidatingResponseHandler.java +++ b/src/main/java/com/github/sardine/impl/handler/ValidatingResponseHandler.java @@ -16,31 +16,32 @@ package com.github.sardine.impl.handler; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; -import org.apache.http.client.ResponseHandler; + +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.io.HttpClientResponseHandler; +import org.apache.hc.core5.http.message.StatusLine; import com.github.sardine.impl.SardineException; /** * Basic response handler which takes an url for documentation. * - * @param return type of {@link ResponseHandler#handleResponse(HttpResponse)}. + * @param return type of {@link HttpClientResponseHandler#handleResponse(ClassicHttpResponse)} (HttpResponse)}. * @author mirko */ -public abstract class ValidatingResponseHandler implements ResponseHandler +public abstract class ValidatingResponseHandler implements HttpClientResponseHandler { /** - * Checks the response for a statuscode between {@link HttpStatus#SC_OK} and {@link HttpStatus#SC_MULTIPLE_CHOICES} + * Checks the response for a statuscode between {@link org.apache.hc.core5.http.HttpStatus#SC_OK} and {@link org.apache.hc.core5.http.HttpStatus#SC_MULTIPLE_CHOICES} * and throws an {@link com.github.sardine.impl.SardineException} otherwise. * * @param response to check * @throws SardineException when the status code is not acceptable. */ - protected void validateResponse(HttpResponse response) throws SardineException + protected void validateResponse(ClassicHttpResponse response) throws SardineException { - StatusLine statusLine = response.getStatusLine(); + StatusLine statusLine = new StatusLine(response); int statusCode = statusLine.getStatusCode(); if (statusCode >= HttpStatus.SC_OK && statusCode < HttpStatus.SC_MULTIPLE_CHOICES) { @@ -48,4 +49,4 @@ protected void validateResponse(HttpResponse response) throws SardineException } throw new SardineException("Unexpected response", statusLine.getStatusCode(), statusLine.getReasonPhrase()); } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/sardine/impl/handler/VoidResponseHandler.java b/src/main/java/com/github/sardine/impl/handler/VoidResponseHandler.java index 9e262fab..271636f1 100644 --- a/src/main/java/com/github/sardine/impl/handler/VoidResponseHandler.java +++ b/src/main/java/com/github/sardine/impl/handler/VoidResponseHandler.java @@ -18,18 +18,19 @@ import java.io.IOException; -import org.apache.http.HttpResponse; +import org.apache.hc.core5.http.ClassicHttpResponse; + /** - * {@link org.apache.http.client.ResponseHandler} which just executes the request and checks the answer is - * in the valid range of {@link ValidatingResponseHandler#validateResponse(org.apache.http.HttpResponse)}. + * {@link org.apache.hc.core5.http.io.HttpClientResponseHandler} which just executes the request and checks the answer is + * in the valid range of {@link ValidatingResponseHandler#validateResponse(ClassicHttpResponse)}. * * @author mirko */ public class VoidResponseHandler extends ValidatingResponseHandler { @Override - public Void handleResponse(HttpResponse response) throws IOException + public Void handleResponse(ClassicHttpResponse response) throws IOException { this.validateResponse(response); return null; diff --git a/src/main/java/com/github/sardine/impl/handler/package-info.java b/src/main/java/com/github/sardine/impl/handler/package-info.java index 93a06a46..f0488afd 100644 --- a/src/main/java/com/github/sardine/impl/handler/package-info.java +++ b/src/main/java/com/github/sardine/impl/handler/package-info.java @@ -15,6 +15,6 @@ */ /** - * Response handler with stauts code validation for {@link org.apache.http.client.HttpClient} implementation. + * Response handler with status code validation for {@link org.apache.hc.client5.http.classic.HttpClient} implementation. */ package com.github.sardine.impl.handler; diff --git a/src/main/java/com/github/sardine/impl/io/ConsumingInputStream.java b/src/main/java/com/github/sardine/impl/io/ConsumingInputStream.java index e7d154aa..69f776b3 100644 --- a/src/main/java/com/github/sardine/impl/io/ConsumingInputStream.java +++ b/src/main/java/com/github/sardine/impl/io/ConsumingInputStream.java @@ -20,9 +20,10 @@ import java.io.FilterInputStream; import java.io.IOException; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.util.EntityUtils; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.io.entity.EntityUtils; + /** * Wrapper for the input stream, will consume the rest of the response on {@link ConsumingInputStream#close()}. @@ -36,7 +37,7 @@ public class ConsumingInputStream extends FilterInputStream * @throws IOException If there is a problem reading from the response * @throws NullPointerException If the response has no message entity */ - public ConsumingInputStream(final HttpResponse response) throws IOException + public ConsumingInputStream(final ClassicHttpResponse response) throws IOException { super(response.getEntity().getContent()); this.entity = response.getEntity(); diff --git a/src/main/java/com/github/sardine/impl/io/ContentLengthInputStream.java b/src/main/java/com/github/sardine/impl/io/ContentLengthInputStream.java index acd680c2..00a45d0b 100644 --- a/src/main/java/com/github/sardine/impl/io/ContentLengthInputStream.java +++ b/src/main/java/com/github/sardine/impl/io/ContentLengthInputStream.java @@ -20,14 +20,15 @@ import java.io.IOException; import java.io.InputStream; -import org.apache.http.HttpResponse; +import org.apache.hc.core5.http.ClassicHttpResponse; + public class ContentLengthInputStream extends FilterInputStream { private Long length; - public ContentLengthInputStream(final HttpResponse response) throws IOException + public ContentLengthInputStream(final ClassicHttpResponse response) throws IOException { super(response.getEntity().getContent()); this.length = response.getEntity().getContentLength(); @@ -61,4 +62,4 @@ public int read(byte[] b, int off, int len) throws IOException { return in.read(b, off, len); } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/sardine/impl/io/HttpMethodReleaseInputStream.java b/src/main/java/com/github/sardine/impl/io/HttpMethodReleaseInputStream.java index 9c594d76..f7431909 100644 --- a/src/main/java/com/github/sardine/impl/io/HttpMethodReleaseInputStream.java +++ b/src/main/java/com/github/sardine/impl/io/HttpMethodReleaseInputStream.java @@ -20,22 +20,24 @@ import java.util.logging.Level; import java.util.logging.Logger; -import org.apache.http.HttpConnection; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpConnection; +import org.apache.hc.core5.http.HttpResponse; + public class HttpMethodReleaseInputStream extends ByteCountInputStream { private static final Logger log = Logger.getLogger(HttpMethodReleaseInputStream.class.getName()); - private HttpResponse response; + private ClassicHttpResponse response; /** * @param response The HTTP response to read from * @throws IOException If there is a problem reading from the response * @throws NullPointerException If the response has no message entity */ - public HttpMethodReleaseInputStream(final HttpResponse response) throws IOException + public HttpMethodReleaseInputStream(final ClassicHttpResponse response) throws IOException { super(response.getEntity().getContent()); this.response = response; @@ -45,8 +47,8 @@ public HttpMethodReleaseInputStream(final HttpResponse response) throws IOExcept * This will force close the connection if the content has not been fully consumed * * @throws IOException if an I/O error occurs - * @see CloseableHttpResponse#close() - * @see HttpConnection#shutdown() + * @see org.apache.hc.client5.http.impl.classic.CloseableHttpResponse#close() + * @see HttpConnection#close() */ @Override public void close() throws IOException diff --git a/src/main/java/com/github/sardine/impl/io/package-info.java b/src/main/java/com/github/sardine/impl/io/package-info.java index 54d6809b..1cbcfb14 100644 --- a/src/main/java/com/github/sardine/impl/io/package-info.java +++ b/src/main/java/com/github/sardine/impl/io/package-info.java @@ -15,6 +15,6 @@ */ /** - * I/O support {@link org.apache.http.client.HttpClient} implementation. + * I/O support {@link org.apache.hc.client5.http.classic.HttpClient} implementation. */ package com.github.sardine.impl.io; diff --git a/src/main/java/com/github/sardine/impl/methods/HttpAcl.java b/src/main/java/com/github/sardine/impl/methods/HttpAcl.java index 2cf9addf..ebba4fba 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpAcl.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpAcl.java @@ -18,17 +18,18 @@ import java.net.URI; -import org.apache.http.HttpHeaders; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.HttpHeaders; + /** * Simple class for making WebDAV ACL requests. */ -public class HttpAcl extends HttpEntityEnclosingRequestBase +public class HttpAcl extends HttpUriRequestBase { public static final String METHOD_NAME = "ACL"; - public HttpAcl(final String uri) + public HttpAcl(String uri) { this(URI.create(uri)); } @@ -36,9 +37,9 @@ public HttpAcl(final String uri) /** * @param uri The resource */ - public HttpAcl(final URI uri) + public HttpAcl(URI uri) { - this.setURI(uri); + super(METHOD_NAME, uri); this.setHeader(HttpHeaders.CONTENT_TYPE, "text/xml; charset=utf-8"); } diff --git a/src/main/java/com/github/sardine/impl/methods/HttpCheckin.java b/src/main/java/com/github/sardine/impl/methods/HttpCheckin.java index afba8f99..248cf73c 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpCheckin.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpCheckin.java @@ -1,13 +1,13 @@ package com.github.sardine.impl.methods; -import org.apache.http.client.methods.HttpRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; import java.net.URI; /** * Simple class for making WebDAV CHECKIN requests. */ -public class HttpCheckin extends HttpRequestBase { +public class HttpCheckin extends HttpUriRequestBase { public static final String METHOD_NAME = "CHECKIN"; @@ -16,7 +16,7 @@ public HttpCheckin(String uri) { } public HttpCheckin(URI uri) { - this.setURI(uri); + super(METHOD_NAME, uri); } @Override diff --git a/src/main/java/com/github/sardine/impl/methods/HttpCheckout.java b/src/main/java/com/github/sardine/impl/methods/HttpCheckout.java index 47b5d668..73fe1a08 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpCheckout.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpCheckout.java @@ -1,13 +1,13 @@ package com.github.sardine.impl.methods; -import org.apache.http.client.methods.HttpRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; import java.net.URI; /** * Simple class for making WebDAV CHECKOUT requests. */ -public class HttpCheckout extends HttpRequestBase { +public class HttpCheckout extends HttpUriRequestBase { public static final String METHOD_NAME = "CHECKOUT"; @@ -16,7 +16,7 @@ public HttpCheckout(String uri) { } public HttpCheckout(URI uri) { - this.setURI(uri); + super(METHOD_NAME, uri); } @Override diff --git a/src/main/java/com/github/sardine/impl/methods/HttpCopy.java b/src/main/java/com/github/sardine/impl/methods/HttpCopy.java index 00e43c03..ca1953fb 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpCopy.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpCopy.java @@ -18,22 +18,23 @@ import java.net.URI; -import org.apache.http.HttpHeaders; -import org.apache.http.client.methods.HttpRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.HttpHeaders; + /** * Simple class for making WebDAV COPY requests. Assumes Overwrite = T. * */ -public class HttpCopy extends HttpRequestBase +public class HttpCopy extends HttpUriRequestBase { public static final String METHOD_NAME = "COPY"; public HttpCopy(URI sourceUrl, URI destinationUrl, boolean overwrite) { + super(METHOD_NAME, sourceUrl); this.setHeader(HttpHeaders.DESTINATION, destinationUrl.toASCIIString()); this.setHeader(HttpHeaders.OVERWRITE, overwrite ? "T" : "F"); - this.setURI(sourceUrl); } public HttpCopy(String sourceUrl, String destinationUrl, boolean overwrite) diff --git a/src/main/java/com/github/sardine/impl/methods/HttpLock.java b/src/main/java/com/github/sardine/impl/methods/HttpLock.java index 8677b22a..7da5a0de 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpLock.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpLock.java @@ -18,23 +18,23 @@ import java.net.URI; -import org.apache.http.HttpHeaders; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.HttpHeaders; /** */ -public class HttpLock extends HttpEntityEnclosingRequestBase +public class HttpLock extends HttpUriRequestBase { public static final String METHOD_NAME = "LOCK"; - public HttpLock(String url) + public HttpLock(String uri) { - this(URI.create(url)); + this(URI.create(uri)); } - public HttpLock(URI url) + public HttpLock(URI uri) { - this.setURI(url); + super(METHOD_NAME, uri); this.setHeader(HttpHeaders.CONTENT_TYPE, "text/xml; charset=utf-8"); } @@ -77,4 +77,4 @@ public void setInfinite() { this.setHeader(HttpHeaders.TIMEOUT, "Infinite"); } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/sardine/impl/methods/HttpMkCol.java b/src/main/java/com/github/sardine/impl/methods/HttpMkCol.java index 17bfa3a2..a73f49f3 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpMkCol.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpMkCol.java @@ -18,27 +18,26 @@ import java.net.URI; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; /** * Simple class for making MKCOL requests. * */ -public class HttpMkCol extends HttpEntityEnclosingRequestBase +public class HttpMkCol extends HttpUriRequestBase { public static final String METHOD_NAME = "MKCOL"; - public HttpMkCol(String url) + public HttpMkCol(String uri) { - this(URI.create(url)); + this(URI.create(uri)); } - public HttpMkCol(URI url) + public HttpMkCol(URI uri) { - this.setURI(url); + super(METHOD_NAME, uri); } - @Override public String getMethod() { return METHOD_NAME; diff --git a/src/main/java/com/github/sardine/impl/methods/HttpMove.java b/src/main/java/com/github/sardine/impl/methods/HttpMove.java index f8a7ca9f..ea87d68c 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpMove.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpMove.java @@ -18,22 +18,24 @@ import java.net.URI; -import org.apache.http.HttpHeaders; -import org.apache.http.client.methods.HttpRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.HttpHeaders; + /** * Simple class for making WebDAV MOVE requests. * */ -public class HttpMove extends HttpRequestBase +public class HttpMove extends HttpUriRequestBase { public static final String METHOD_NAME = "MOVE"; public HttpMove(URI sourceUrl, URI destinationUrl, boolean overwrite) { + super(METHOD_NAME, destinationUrl); this.setHeader(HttpHeaders.DESTINATION, destinationUrl.toASCIIString()); this.setHeader(HttpHeaders.OVERWRITE, overwrite ? "T" : "F"); - this.setURI(sourceUrl); + this.setUri(sourceUrl); } public HttpMove(String sourceUrl, String destinationUrl, boolean overwrite) diff --git a/src/main/java/com/github/sardine/impl/methods/HttpPropFind.java b/src/main/java/com/github/sardine/impl/methods/HttpPropFind.java index 536296af..a97ef2da 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpPropFind.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpPropFind.java @@ -18,18 +18,18 @@ import java.net.URI; -import org.apache.http.HttpHeaders; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.HttpHeaders; /** * Simple class for making WebDAV PROPFIND requests. * */ -public class HttpPropFind extends HttpEntityEnclosingRequestBase +public class HttpPropFind extends HttpUriRequestBase { public static final String METHOD_NAME = "PROPFIND"; - public HttpPropFind(final String uri) + public HttpPropFind(String uri) { this(URI.create(uri)); } @@ -40,10 +40,10 @@ public HttpPropFind(final String uri) * * @param uri The resource */ - public HttpPropFind(final URI uri) + public HttpPropFind(URI uri) { + super(METHOD_NAME, uri); this.setDepth("1"); - this.setURI(uri); this.setHeader(HttpHeaders.CONTENT_TYPE, "text/xml; charset=utf-8"); } diff --git a/src/main/java/com/github/sardine/impl/methods/HttpPropPatch.java b/src/main/java/com/github/sardine/impl/methods/HttpPropPatch.java index 340e8a8e..007f98b8 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpPropPatch.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpPropPatch.java @@ -18,25 +18,25 @@ import java.net.URI; -import org.apache.http.HttpHeaders; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.HttpHeaders; /** * Simple class for making WebDAV PROPPATCH requests. * */ -public class HttpPropPatch extends HttpEntityEnclosingRequestBase +public class HttpPropPatch extends HttpUriRequestBase { public static final String METHOD_NAME = "PROPPATCH"; - public HttpPropPatch(String url) + public HttpPropPatch(String uri) { - this(URI.create(url)); + this(URI.create(uri)); } - public HttpPropPatch(URI url) + public HttpPropPatch(URI uri) { - this.setURI(url); + super(METHOD_NAME, uri); this.setHeader(HttpHeaders.CONTENT_TYPE, "text/xml; charset=utf-8"); } diff --git a/src/main/java/com/github/sardine/impl/methods/HttpReport.java b/src/main/java/com/github/sardine/impl/methods/HttpReport.java index 22f2b9c0..3cca9674 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpReport.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpReport.java @@ -2,46 +2,41 @@ import java.net.URI; -import org.apache.http.HttpHeaders; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; - -public class HttpReport extends HttpEntityEnclosingRequestBase -{ - public static final String METHOD_NAME = "REPORT"; - - public HttpReport(final String uri) - { - this(URI.create(uri)); - } - - /** - * Sets the Depth request header to 0, meaning the - * report applies to the resource only. - * - * @param uri The resource - */ - public HttpReport(final URI uri) - { - this.setURI(uri); - this.setDepth("0"); - this.setHeader(HttpHeaders.CONTENT_TYPE, "text/xml; charset=utf-8"); - } - - @Override - public String getMethod() - { - return METHOD_NAME; - } - - /** - * A client may submit a Depth header with a value of "0", "1", or "infinity" with - * a {@link com.github.sardine.model.Propfind} on a collection resource with internal member URIs. - * - * @param depth "0", "1" or "infinity". - */ - public HttpReport setDepth(String depth) - { - this.setHeader(HttpHeaders.DEPTH, depth); - return this; - } +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.HttpHeaders; + + +public class HttpReport extends HttpUriRequestBase { + public static final String METHOD_NAME = "REPORT"; + + public HttpReport(String uri) { + this(URI.create(uri)); + } + + /** + * Sets the Depth request header to 0, meaning the report applies to the resource only. + * + * @param uri The resource + */ + public HttpReport(URI uri) { + super(METHOD_NAME, uri); + this.setDepth("0"); + this.setHeader(HttpHeaders.CONTENT_TYPE, "text/xml; charset=utf-8"); + } + + @Override + public String getMethod() { + return METHOD_NAME; + } + + /** + * A client may submit a Depth header with a value of "0", "1", or "infinity" with a + * {@link com.github.sardine.model.Propfind} on a collection resource with internal member URIs. + * + * @param depth "0", "1" or "infinity". + */ + public HttpReport setDepth(String depth) { + this.setHeader(HttpHeaders.DEPTH, depth); + return this; + } } diff --git a/src/main/java/com/github/sardine/impl/methods/HttpSearch.java b/src/main/java/com/github/sardine/impl/methods/HttpSearch.java index baf7a8dd..57ecd9d6 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpSearch.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpSearch.java @@ -5,31 +5,26 @@ import java.net.URI; -import org.apache.http.HttpHeaders; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.HttpHeaders; /** * @author Gary Williams */ -public class HttpSearch - extends HttpEntityEnclosingRequestBase -{ - public static final String METHOD_NAME = "SEARCH"; - - public HttpSearch(final String uri) - { - this(URI.create(uri)); - } - - public HttpSearch(final URI uri) - { - this.setURI(uri); - this.setHeader(HttpHeaders.CONTENT_TYPE, "text/xml; charset=utf-8"); - } - - @Override - public String getMethod() - { - return METHOD_NAME; - } +public class HttpSearch extends HttpUriRequestBase { + public static final String METHOD_NAME = "SEARCH"; + + public HttpSearch(String uri) { + this(URI.create(uri)); + } + + public HttpSearch(URI uri) { + super(METHOD_NAME, uri); + this.setHeader(HttpHeaders.CONTENT_TYPE, "text/xml; charset=utf-8"); + } + + @Override + public String getMethod() { + return METHOD_NAME; + } } diff --git a/src/main/java/com/github/sardine/impl/methods/HttpUnlock.java b/src/main/java/com/github/sardine/impl/methods/HttpUnlock.java index b6f21e1a..5c2c907c 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpUnlock.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpUnlock.java @@ -18,42 +18,39 @@ import java.net.URI; -import org.apache.http.HttpHeaders; -import org.apache.http.client.methods.HttpRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.HttpHeaders; /** + * */ -public class HttpUnlock extends HttpRequestBase -{ - public static final String METHOD_NAME = "UNLOCK"; +public class HttpUnlock extends HttpUriRequestBase { + public static final String METHOD_NAME = "UNLOCK"; - /** - * @param url The resource - * @param token The Lock-Token request header is used with the UNLOCK method to identify the lock to be removed. - * The lock token in the Lock-Token request header must identify a lock that contains the resource - * identified by Request-URI as a member. - */ - public HttpUnlock(String url, String token) - { - this(URI.create(url), token); - } + /** + * @param uri The resource + * @param token The Lock-Token request header is used with the UNLOCK method to identify the lock to be removed. The + * lock token in the Lock-Token request header must identify a lock that contains the resource + * identified by Request-URI as a member. + */ + public HttpUnlock(String uri, String token) { + this(URI.create(uri), token); + } - /** - * @param url The resource - * @param token The Lock-Token request header is used with the UNLOCK method to identify the lock to be removed. - * The lock token in the Lock-Token request header must identify a lock that contains the resource - * identified by Request-URI as a member. - */ - public HttpUnlock(URI url, String token) - { - this.setURI(url); - this.setHeader(HttpHeaders.CONTENT_TYPE, "text/xml; charset=utf-8"); - this.setHeader("Lock-Token", "<" + token + ">"); - } + /** + * @param uri The resource + * @param token The Lock-Token request header is used with the UNLOCK method to identify the lock to be removed. The + * lock token in the Lock-Token request header must identify a lock that contains the resource + * identified by Request-URI as a member. + */ + public HttpUnlock(URI uri, String token) { + super(METHOD_NAME, uri); + this.setHeader(HttpHeaders.CONTENT_TYPE, "text/xml; charset=utf-8"); + this.setHeader("Lock-Token", "<" + token + ">"); + } - @Override - public String getMethod() - { - return METHOD_NAME; - } + @Override + public String getMethod() { + return METHOD_NAME; + } } diff --git a/src/main/java/com/github/sardine/impl/methods/HttpVersionControl.java b/src/main/java/com/github/sardine/impl/methods/HttpVersionControl.java index d41e8fd5..213a8d85 100644 --- a/src/main/java/com/github/sardine/impl/methods/HttpVersionControl.java +++ b/src/main/java/com/github/sardine/impl/methods/HttpVersionControl.java @@ -1,13 +1,13 @@ package com.github.sardine.impl.methods; -import org.apache.http.client.methods.HttpRequestBase; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; import java.net.URI; /** * Simple class for making WebDAV VERSION-CONTROL requests. */ -public class HttpVersionControl extends HttpRequestBase { +public class HttpVersionControl extends HttpUriRequestBase { public static final String METHOD_NAME = "VERSION-CONTROL"; @@ -16,7 +16,7 @@ public HttpVersionControl(String uri) { } public HttpVersionControl(URI uri) { - this.setURI(uri); + super(METHOD_NAME, uri); } @Override diff --git a/src/main/java/com/github/sardine/impl/methods/package-info.java b/src/main/java/com/github/sardine/impl/methods/package-info.java index 0c1fb838..239794d3 100644 --- a/src/main/java/com/github/sardine/impl/methods/package-info.java +++ b/src/main/java/com/github/sardine/impl/methods/package-info.java @@ -15,6 +15,6 @@ */ /** - * WebDAV methods for {@link org.apache.http.client.HttpClient} implementation. + * WebDAV methods for {@link org.apache.hc.client5.http.classic.HttpClient} implementation. */ package com.github.sardine.impl.methods; diff --git a/src/main/java/com/github/sardine/impl/package-info.java b/src/main/java/com/github/sardine/impl/package-info.java index 85eab44d..f63c28d7 100644 --- a/src/main/java/com/github/sardine/impl/package-info.java +++ b/src/main/java/com/github/sardine/impl/package-info.java @@ -1,4 +1,4 @@ /** - * Assembles classes only related to the {@link org.apache.http.client.HttpClient} implementation. + * Assembles classes only related to the {@link org.apache.hc.client5.http.classic.HttpClient} implementation. */ package com.github.sardine.impl; diff --git a/src/main/java/com/github/sardine/util/SardineUtil.java b/src/main/java/com/github/sardine/util/SardineUtil.java index f47488b9..4deeed00 100644 --- a/src/main/java/com/github/sardine/util/SardineUtil.java +++ b/src/main/java/com/github/sardine/util/SardineUtil.java @@ -1,25 +1,11 @@ package com.github.sardine.util; -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; -import java.io.StringWriter; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.XMLConstants; -import javax.xml.namespace.QName; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.sax.SAXSource; - -import org.apache.http.client.utils.DateUtils; +import com.github.sardine.model.ObjectFactory; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import jakarta.xml.bind.Marshaller; +import jakarta.xml.bind.Unmarshaller; +import org.apache.hc.client5.http.utils.DateUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; @@ -27,12 +13,20 @@ import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; -import com.github.sardine.model.ObjectFactory; - -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.JAXBException; -import jakarta.xml.bind.Marshaller; -import jakarta.xml.bind.Unmarshaller; +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.sax.SAXSource; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.*; /** * Basic utility code. I borrowed some code from the webdavlib for @@ -44,16 +38,16 @@ public final class SardineUtil { private SardineUtil() {} - private final static String[] SUPPORTED_DATE_FORMATS = new String[]{ - "yyyy-MM-dd'T'HH:mm:ss'Z'", - "EEE, dd MMM yyyy HH:mm:ss zzz", - "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", - "yyyy-MM-dd'T'HH:mm:ssZ", - "EEE MMM dd HH:mm:ss zzz yyyy", - "EEEEEE, dd-MMM-yy HH:mm:ss zzz", - "EEE MMMM d HH:mm:ss yyyy"}; + private final static String[] SUPPORTED_DATE_FORMATS = new String[]{ + "yyyy-MM-dd'T'HH:mm:ss'Z'", + "EEE, dd MMM yyyy HH:mm:ss zzz", // RFC1123 + "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", + "yyyy-MM-dd'T'HH:mm:ssZ", + "EEE MMM dd HH:mm:ss zzz yyyy", + "EEEE, dd-MMM-yy HH:mm:ss zzz", + "EEE MMMM d HH:mm:ss yyyy"}; - /** + /** * Default namespace prefix */ public static final String CUSTOM_NAMESPACE_PREFIX = "s"; @@ -92,19 +86,6 @@ private SardineUtil() {} } } - /** - * Date formats using for Date parsing. - */ - private static final List> DATETIME_FORMATS; - - static { - List> l = new ArrayList>(SUPPORTED_DATE_FORMATS.length); - for (int i = 0; i()); - } - DATETIME_FORMATS = Collections.unmodifiableList(l); - } - /** * Loops over all the possible date formats and tries to find the right one. * @@ -117,7 +98,13 @@ public static Date parseDate(String value) { return null; } - return DateUtils.parseDate(value, SUPPORTED_DATE_FORMATS); + final Instant parsedInstant = DateUtils.parseDate(value, Arrays.stream(SUPPORTED_DATE_FORMATS) + .map(pattern -> DateTimeFormatter.ofPattern(pattern, Locale.US).withZone(ZoneId.of("GMT"))).toArray(DateTimeFormatter[]::new)); + if (null == parsedInstant) + { + return null; + } + return Date.from(parsedInstant); } @SuppressWarnings("unchecked") @@ -171,10 +158,7 @@ public static T unmarshal(InputStream in) throws IOException catch (JAXBException e) { // Server does not return any valid WebDAV XML that matches our JAXB context - IOException failure = new IOException("Not a valid DAV response"); - // Backward compatibility - failure.initCause(e); - throw failure; + throw new IOException("Not a valid DAV response", e); } finally { diff --git a/src/test/java/com/github/sardine/AuthenticationTest.java b/src/test/java/com/github/sardine/AuthenticationTest.java index 702f323e..c99bf4d4 100644 --- a/src/test/java/com/github/sardine/AuthenticationTest.java +++ b/src/test/java/com/github/sardine/AuthenticationTest.java @@ -26,11 +26,12 @@ import java.util.List; import java.util.concurrent.CountDownLatch; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.BasicUserPrincipal; -import org.apache.http.auth.Credentials; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.BasicUserPrincipal; +import org.apache.hc.client5.http.auth.Credentials; +import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.core5.http.protocol.HttpContext; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -95,7 +96,7 @@ public void testBasicPreemptiveAuth() throws Exception client.setDefaultCredentialsProvider(new BasicCredentialsProvider() { @Override - public Credentials getCredentials(AuthScope authscope) + public Credentials getCredentials(AuthScope authscope, HttpContext httpContext) { // Set flag that credentials have been used indicating preemptive authentication count.countDown(); @@ -106,9 +107,9 @@ public Principal getUserPrincipal() return new BasicUserPrincipal("anonymous"); } - public String getPassword() + public char[] getPassword() { - return "invalid"; + return "invalid".toCharArray(); } }; } diff --git a/src/test/java/com/github/sardine/FunctionalSardineTest.java b/src/test/java/com/github/sardine/FunctionalSardineTest.java index bc3e6054..793ad75a 100644 --- a/src/test/java/com/github/sardine/FunctionalSardineTest.java +++ b/src/test/java/com/github/sardine/FunctionalSardineTest.java @@ -39,12 +39,11 @@ import javax.xml.namespace.QName; -import org.apache.http.HttpClientConnection; -import org.apache.http.HttpHeaders; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.HttpResponseInterceptor; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.io.ConnectionEndpoint; +import org.apache.hc.core5.http.HttpHeaders; +import org.apache.hc.core5.util.TimeValue; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -77,8 +76,8 @@ public void testGetFileContentEncoding() throws Exception { final AtomicBoolean intercept = new AtomicBoolean(); final HttpClientBuilder builder = HttpClientBuilder.create(); - builder.addInterceptorFirst((HttpResponseInterceptor) (r, context) -> { - if (r.getStatusLine().getStatusCode() == 200) { + builder.addResponseInterceptorFirst((r, e, context) -> { + if (r.getCode() == 200) { intercept.set(true); assertNotNull(r.getHeaders(HttpHeaders.CONTENT_ENCODING)); assertEquals(1, r.getHeaders(HttpHeaders.CONTENT_ENCODING).length); @@ -111,61 +110,10 @@ public void testReadEmptyFile() throws Exception in.close(); } - @Test - public void testReadCloseNotFullyConsumed() throws Exception - { - // 3 requests in total - final CountDownLatch c = new CountDownLatch(3); - final HttpClientBuilder builder = HttpClientBuilder.create(); - builder.setConnectionManager(new PoolingHttpClientConnectionManager(Long.MAX_VALUE, TimeUnit.MILLISECONDS) { - @Override - public synchronized void releaseConnection(HttpClientConnection conn, Object state, long keepalive, TimeUnit tunit) { - switch ((int) c.getCount()) { - case 3: - case 1: - // DELETE - // PUT - assertTrue(conn.isOpen()); - break; - case 2: - // GET - assertFalse(conn.isOpen()); - break; - default: - fail(); - } - super.releaseConnection(conn, state, keepalive, tunit); - c.countDown(); - } - }); - Sardine sardine = new SardineImpl(builder); - // Make sure the response is not compressed - sardine.disableCompression(); - final String url = webDavTestContainer.getRandomTestFileUrl(); - try { - final byte[] content = "sa".getBytes(StandardCharsets.UTF_8); - assertEquals(2, content.length); - sardine.put(url, new ByteArrayInputStream(content)); - final InputStream in = sardine.get(url); - assertNotNull(in); - assertEquals('s', in.read()); - in.close(); - } finally { - sardine.delete(url); - } - } - @Test public void testReadCloseFullyConsumed() throws Exception { final HttpClientBuilder builder = HttpClientBuilder.create(); - builder.setConnectionManager(new PoolingHttpClientConnectionManager(Long.MAX_VALUE, TimeUnit.MILLISECONDS) { - @Override - public synchronized void releaseConnection(HttpClientConnection conn, Object state, long keepalive, TimeUnit tunit) { - assertTrue(conn.isOpen()); - super.releaseConnection(conn, state, keepalive, tunit); - } - }); Sardine sardine = new SardineImpl(builder); // Make sure the response is not compressed sardine.disableCompression(); @@ -300,8 +248,8 @@ public void testPutRange() throws Exception { final AtomicBoolean intercept = new AtomicBoolean(); final HttpClientBuilder client = HttpClientBuilder.create(); - client.addInterceptorFirst((HttpResponseInterceptor) (r, context) -> { - if (r.getStatusLine().getStatusCode() == 201) { + client.addResponseInterceptorFirst((r, e, context) -> { + if (r.getCode()== 201) { intercept.set(true); } }); @@ -314,12 +262,12 @@ public void testPutRange() throws Exception final Map header = Collections.singletonMap(HttpHeaders.CONTENT_RANGE, "bytes " + 2 + "-" + 3 + "/" + 4); - client.addInterceptorFirst((HttpRequestInterceptor) (r, context) -> { + client.addRequestInterceptorFirst((r, e, context) -> { assertNotNull(r.getHeaders(HttpHeaders.CONTENT_RANGE)); assertEquals(1, r.getHeaders(HttpHeaders.CONTENT_RANGE).length); }); - client.addInterceptorFirst((HttpResponseInterceptor) (r, context) -> assertEquals(204, r.getStatusLine().getStatusCode())); - sardine.put(url, new ByteArrayInputStream("st".getBytes(StandardCharsets.UTF_8)), header); + client.addResponseInterceptorFirst((r, e, context) -> assertEquals(204, r.getCode())); + sardine.put(url, new ByteArrayInputStream("st".getBytes(StandardCharsets.UTF_8)),null, header); assertEquals("Test", new BufferedReader(new InputStreamReader(sardine.get(url), StandardCharsets.UTF_8)).readLine()); @@ -334,8 +282,8 @@ public void testGetRange() throws Exception { final AtomicBoolean intercept = new AtomicBoolean(); final HttpClientBuilder builder = HttpClientBuilder.create(); - builder.addInterceptorFirst((HttpResponseInterceptor) (r, context) -> { - if (r.getStatusLine().getStatusCode() == 206) { + builder.addResponseInterceptorFirst((r, e, context) -> { + if (r.getCode() == 206) { intercept.set(true); // Verify partial content response assertNotNull(r.getHeaders(HttpHeaders.CONTENT_RANGE)); @@ -365,7 +313,6 @@ public void testPutExpectContinue() throws Exception final String url = webDavTestContainer.getRandomTestBasicAuthFileUrl(); try { sardine.put(url, new InputStream() { - @Override public int read() { fail("Expected authentication to fail without sending any body"); return -1; diff --git a/src/test/java/com/github/sardine/SardineUtilTest.java b/src/test/java/com/github/sardine/SardineUtilTest.java index 8db4e142..dbc62e87 100644 --- a/src/test/java/com/github/sardine/SardineUtilTest.java +++ b/src/test/java/com/github/sardine/SardineUtilTest.java @@ -34,6 +34,7 @@ public class SardineUtilTest @Test public void testParseDate() throws Exception { + assertNotNull(SardineUtil.parseDate("1970-01-01T12:00:00Z")); assertNotNull(SardineUtil.parseDate("2007-07-16T13:35:49Z")); assertNotNull(SardineUtil.parseDate("Mon, 16 Jul 2007 13:35:49 GMT")); }