From 63be9fa1ae1d45502a3e7b4792e79df36e835da0 Mon Sep 17 00:00:00 2001 From: Aayush Atharva Date: Sun, 3 Sep 2023 15:36:59 +0530 Subject: [PATCH] Drop WebDAV Support (#1900) --- .../webdav/WebDavCompletionHandlerBase.java | 192 ------------------ .../webdav/WebDavResponse.java | 139 ------------- .../asynchttpclient/webdav/WebdavTest.java | 179 ---------------- 3 files changed, 510 deletions(-) delete mode 100644 client/src/main/java/org/asynchttpclient/webdav/WebDavCompletionHandlerBase.java delete mode 100644 client/src/main/java/org/asynchttpclient/webdav/WebDavResponse.java delete mode 100644 client/src/test/java/org/asynchttpclient/webdav/WebdavTest.java diff --git a/client/src/main/java/org/asynchttpclient/webdav/WebDavCompletionHandlerBase.java b/client/src/main/java/org/asynchttpclient/webdav/WebDavCompletionHandlerBase.java deleted file mode 100644 index bf57ddd21..000000000 --- a/client/src/main/java/org/asynchttpclient/webdav/WebDavCompletionHandlerBase.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2010-2012 Sonatype, Inc. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ -package org.asynchttpclient.webdav; - -import io.netty.handler.codec.http.HttpHeaders; -import org.asynchttpclient.AsyncHandler; -import org.asynchttpclient.HttpResponseBodyPart; -import org.asynchttpclient.HttpResponseStatus; -import org.asynchttpclient.Response; -import org.asynchttpclient.netty.NettyResponse; -import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.io.InputStream; -import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Future; - -/** - * Simple {@link AsyncHandler} that add support for WebDav's response manipulation. - * - * @param the result type - */ -public abstract class WebDavCompletionHandlerBase implements AsyncHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(WebDavCompletionHandlerBase.class); - private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY; - private final List bodyParts = Collections.synchronizedList(new ArrayList<>()); - private @Nullable HttpResponseStatus status; - private @Nullable HttpHeaders headers; - - static { - DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance(); - if (Boolean.getBoolean("org.asynchttpclient.webdav.enableDtd")) { - try { - DOCUMENT_BUILDER_FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - } catch (ParserConfigurationException e) { - LOGGER.error("Failed to disable doctype declaration"); - throw new ExceptionInInitializerError(e); - } - } - } - - @Override - public final State onBodyPartReceived(final HttpResponseBodyPart content) { - bodyParts.add(content); - return State.CONTINUE; - } - - @Override - public final State onStatusReceived(final HttpResponseStatus status) { - this.status = status; - return State.CONTINUE; - } - - @Override - public final State onHeadersReceived(final HttpHeaders headers) { - this.headers = headers; - return State.CONTINUE; - } - - private Document readXMLResponse(InputStream stream, HttpResponseStatus initialStatus) { - Document document; - try { - document = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder().parse(stream); - status = parse(document, initialStatus); - } catch (SAXException | IOException | ParserConfigurationException e) { - LOGGER.error(e.getMessage(), e); - throw new RuntimeException(e); - } - return document; - } - - private static HttpResponseStatus parse(Document document, HttpResponseStatus initialStatus) { - HttpResponseStatus status = initialStatus; - Element element = document.getDocumentElement(); - NodeList statusNode = element.getElementsByTagName("status"); - for (int i = 0; i < statusNode.getLength(); i++) { - Node node = statusNode.item(i); - - String value = node.getFirstChild().getNodeValue(); - int statusCode = Integer.parseInt(value.substring(value.indexOf(' '), value.lastIndexOf(' ')).trim()); - String statusText = value.substring(value.lastIndexOf(' ')); - status = new HttpStatusWrapper(status, statusText, statusCode); - } - return status; - } - - @Override - public final T onCompleted() throws Exception { - if (status != null) { - Document document = null; - if (status.getStatusCode() == 207) { - document = readXMLResponse(new NettyResponse(status, headers, bodyParts).getResponseBodyAsStream(), status); - } - // recompute response as readXMLResponse->parse might have updated it - return onCompleted(new WebDavResponse(new NettyResponse(status, headers, bodyParts), document)); - } else { - throw new IllegalStateException("Status is null"); - } - } - - @Override - public void onThrowable(Throwable t) { - LOGGER.debug(t.getMessage(), t); - } - - /** - * Invoked once the HTTP response has been fully read. - * - * @param response The {@link Response} - * @return Type of the value that will be returned by the associated {@link Future} - * @throws Exception if something wrong happens - */ - public abstract T onCompleted(WebDavResponse response) throws Exception; - - private static class HttpStatusWrapper extends HttpResponseStatus { - - private final HttpResponseStatus wrapped; - - private final String statusText; - - private final int statusCode; - - HttpStatusWrapper(HttpResponseStatus wrapper, String statusText, int statusCode) { - super(wrapper.getUri()); - wrapped = wrapper; - this.statusText = statusText; - this.statusCode = statusCode; - } - - @Override - public int getStatusCode() { - return statusText == null ? wrapped.getStatusCode() : statusCode; - } - - @Override - public String getStatusText() { - return statusText == null ? wrapped.getStatusText() : statusText; - } - - @Override - public String getProtocolName() { - return wrapped.getProtocolName(); - } - - @Override - public int getProtocolMajorVersion() { - return wrapped.getProtocolMajorVersion(); - } - - @Override - public int getProtocolMinorVersion() { - return wrapped.getProtocolMinorVersion(); - } - - @Override - public String getProtocolText() { - return wrapped.getStatusText(); - } - - @Override - public SocketAddress getRemoteAddress() { - return wrapped.getRemoteAddress(); - } - - @Override - public SocketAddress getLocalAddress() { - return wrapped.getLocalAddress(); - } - } -} diff --git a/client/src/main/java/org/asynchttpclient/webdav/WebDavResponse.java b/client/src/main/java/org/asynchttpclient/webdav/WebDavResponse.java deleted file mode 100644 index 650212d2e..000000000 --- a/client/src/main/java/org/asynchttpclient/webdav/WebDavResponse.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2010-2012 Sonatype, Inc. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ -package org.asynchttpclient.webdav; - -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.cookie.Cookie; -import org.asynchttpclient.Response; -import org.asynchttpclient.uri.Uri; -import org.jetbrains.annotations.Nullable; -import org.w3c.dom.Document; - -import java.io.InputStream; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.List; - -/** - * Customized {@link Response} which add support for getting the response's body as an XML document (@link WebDavResponse#getBodyAsXML} - */ -public class WebDavResponse implements Response { - - private final Response response; - private final @Nullable Document document; - - WebDavResponse(Response response, @Nullable Document document) { - this.response = response; - this.document = document; - } - - @Override - public int getStatusCode() { - return response.getStatusCode(); - } - - @Override - public String getStatusText() { - return response.getStatusText(); - } - - @Override - public byte[] getResponseBodyAsBytes() { - return response.getResponseBodyAsBytes(); - } - - @Override - public ByteBuffer getResponseBodyAsByteBuffer() { - return response.getResponseBodyAsByteBuffer(); - } - - @Override - public InputStream getResponseBodyAsStream() { - return response.getResponseBodyAsStream(); - } - - @Override - public String getResponseBody() { - return response.getResponseBody(); - } - - @Override - public String getResponseBody(Charset charset) { - return response.getResponseBody(charset); - } - - @Override - public Uri getUri() { - return response.getUri(); - } - - @Override - public String getContentType() { - return response.getContentType(); - } - - @Override - public String getHeader(CharSequence name) { - return response.getHeader(name); - } - - @Override - public List getHeaders(CharSequence name) { - return response.getHeaders(name); - } - - @Override - public HttpHeaders getHeaders() { - return response.getHeaders(); - } - - @Override - public boolean isRedirected() { - return response.isRedirected(); - } - - @Override - public List getCookies() { - return response.getCookies(); - } - - @Override - public boolean hasResponseStatus() { - return response.hasResponseStatus(); - } - - @Override - public boolean hasResponseHeaders() { - return response.hasResponseHeaders(); - } - - @Override - public boolean hasResponseBody() { - return response.hasResponseBody(); - } - - @Override - public SocketAddress getRemoteAddress() { - return response.getRemoteAddress(); - } - - @Override - public SocketAddress getLocalAddress() { - return response.getLocalAddress(); - } - - public @Nullable Document getBodyAsXML() { - return document; - } -} diff --git a/client/src/test/java/org/asynchttpclient/webdav/WebdavTest.java b/client/src/test/java/org/asynchttpclient/webdav/WebdavTest.java deleted file mode 100644 index ce351c03e..000000000 --- a/client/src/test/java/org/asynchttpclient/webdav/WebdavTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2010-2012 Sonatype, Inc. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ -package org.asynchttpclient.webdav; - -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import org.apache.catalina.Context; -import org.apache.catalina.servlets.WebdavServlet; -import org.apache.catalina.startup.Tomcat; -import org.asynchttpclient.AsyncHttpClient; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; - -import java.io.File; -import java.util.Enumeration; - -import static org.asynchttpclient.Dsl.asyncHttpClient; -import static org.asynchttpclient.Dsl.delete; - -public class WebdavTest { - - private Tomcat tomcat; - private int port1; - - @SuppressWarnings("serial") - @BeforeEach - public void setUpGlobal() throws Exception { - String path = new File(".").getAbsolutePath() + "/target"; - - tomcat = new Tomcat(); - tomcat.setHostname("localhost"); - tomcat.setPort(0); - tomcat.setBaseDir(path); - Context ctx = tomcat.addContext("", path); - - Tomcat.addServlet(ctx, "webdav", new WebdavServlet() { - @Override - public void init(ServletConfig config) throws ServletException { - - super.init(new ServletConfig() { - - @Override - public String getServletName() { - return config.getServletName(); - } - - @Override - public ServletContext getServletContext() { - return config.getServletContext(); - } - - @Override - public Enumeration getInitParameterNames() { - // FIXME - return config.getInitParameterNames(); - } - - @Override - public String getInitParameter(String name) { - switch (name) { - case "readonly": - return "false"; - case "listings": - return "true"; - default: - return config.getInitParameter(name); - } - } - }); - } - - }); - ctx.addServletMappingDecoded("/*", "webdav"); - tomcat.start(); - port1 = tomcat.getConnector().getLocalPort(); - } - - @AfterEach - public void tearDownGlobal() throws Exception { - tomcat.stop(); - } - - private String getTargetUrl() { - return String.format("http://localhost:%s/folder1", port1); - } - - @AfterEach - public void clean() throws Exception { - try (AsyncHttpClient client = asyncHttpClient()) { - client.executeRequest(delete(getTargetUrl())).get(); - } - } - -// @RepeatedIfExceptionsTest(repeats = 5) -// public void mkcolWebDavTest1() throws Exception { -// try (AsyncHttpClient client = asyncHttpClient()) { -// Request mkcolRequest = new RequestBuilder("MKCOL").setUrl(getTargetUrl()).build(); -// Response response = client.executeRequest(mkcolRequest).get(); -// assertEquals(201, response.getStatusCode()); -// } -// } -// -// @RepeatedIfExceptionsTest(repeats = 5) -// public void mkcolWebDavTest2() throws Exception { -// try (AsyncHttpClient client = asyncHttpClient()) { -// Request mkcolRequest = new RequestBuilder("MKCOL").setUrl(getTargetUrl() + "/folder2").build(); -// Response response = client.executeRequest(mkcolRequest).get(); -// assertEquals(409, response.getStatusCode()); -// } -// } -// -// @RepeatedIfExceptionsTest(repeats = 5) -// public void basicPropFindWebDavTest() throws Exception { -// try (AsyncHttpClient client = asyncHttpClient()) { -// Request propFindRequest = new RequestBuilder("PROPFIND").setUrl(getTargetUrl()).build(); -// Response response = client.executeRequest(propFindRequest).get(); -// -// assertEquals(404, response.getStatusCode()); -// } -// } -// -// @RepeatedIfExceptionsTest(repeats = 5) -// public void propFindWebDavTest() throws Exception { -// try (AsyncHttpClient client = asyncHttpClient()) { -// Request mkcolRequest = new RequestBuilder("MKCOL").setUrl(getTargetUrl()).build(); -// Response response = client.executeRequest(mkcolRequest).get(); -// assertEquals(201, response.getStatusCode()); -// -// Request putRequest = put(getTargetUrl() + "/Test.txt").setBody("this is a test").build(); -// response = client.executeRequest(putRequest).get(); -// assertEquals(201, response.getStatusCode()); -// -// Request propFindRequest = new RequestBuilder("PROPFIND").setUrl(getTargetUrl() + "/Test.txt").build(); -// response = client.executeRequest(propFindRequest).get(); -// -// assertEquals(207, response.getStatusCode()); -// String body = response.getResponseBody(); -// assertTrue(body.contains("HTTP/1.1 200"), "Got " + body); -// } -// } -// -// @RepeatedIfExceptionsTest(repeats = 5) -// public void propFindCompletionHandlerWebDavTest() throws Exception { -// try (AsyncHttpClient c = asyncHttpClient()) { -// Request mkcolRequest = new RequestBuilder("MKCOL").setUrl(getTargetUrl()).build(); -// Response response = c.executeRequest(mkcolRequest).get(); -// assertEquals(201, response.getStatusCode()); -// -// Request propFindRequest = new RequestBuilder("PROPFIND").setUrl(getTargetUrl()).build(); -// WebDavResponse webDavResponse = c.executeRequest(propFindRequest, new WebDavCompletionHandlerBase() { -// -// @Override -// public void onThrowable(Throwable t) { -// t.printStackTrace(); -// } -// -// @Override -// public WebDavResponse onCompleted(WebDavResponse response) { -// return response; -// } -// }).get(); -// -// assertEquals(207, webDavResponse.getStatusCode()); -// String body = webDavResponse.getResponseBody(); -// assertTrue(body.contains("HTTP/1.1 200"), "Got " + body); -// } -// } -}