MNT-21602 : Revive DownloadContentServlet.java (#910)

* MNT-21602 : Revive DownloadContentServlet.java
   Remove doHEAD method from DownloadContentServlet
   doGET method now redirects to V1 REST - GET /nodes/{nodeId}
   Removed leftover org.alfresco.web.app.servlet.UploadContentServlet, org.alfresco.web.app.servlet.DownloadRawContentServlet and org.alfresco.web.app.servlet.GuestDownloadContentServlet from web.xml as those servlet implementation does not exist.
   Refactor javadoc.
   Add TAS tests to Rest-API/DownloadContentServletTests class
   Restrict DownloadContentServlet to allow only nodes from the workspace://SpacesStore/

* Add downloadContentServlet mapping in web.xml
This commit is contained in:
Alexandru-Eusebiu Epure
2020-07-08 14:31:16 +03:00
committed by GitHub
parent 2ed4dc48ce
commit 66664d40de
4 changed files with 467 additions and 0 deletions

View File

@@ -0,0 +1,324 @@
package org.alfresco.rest.servlet;
import io.restassured.RestAssured;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.core.RestRequest;
import org.alfresco.rest.core.RestResponse;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FileType;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.TestGroup;
import org.alfresco.utility.model.UserModel;
import org.alfresco.utility.report.Bug;
import org.alfresco.utility.testrail.ExecutionType;
import org.alfresco.utility.testrail.annotation.TestRail;
import org.apache.commons.codec.binary.Base64;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
public class DownloadContentServletTests extends RestTest
{
private static final String CONTENT_DISPOSITION = "Content-Disposition";
private static final String FILENAME_HEADER = "filename=\"%s\"";
private static final String ATTACHMENT = "attachment";
private static final String FILE_CONTENT = "The content of the file.";
private static String downloadContentServletAttach = "alfresco/d/a/workspace/SpacesStore/";
private static String downloadContentServletDirect = "alfresco/d/d/workspace/SpacesStore/";
private UserModel testUser;
private FileModel testContentFile;
private String authHeaderEncoded;
@BeforeClass(alwaysRun = true)
public void dataPreparation() throws Exception
{
testUser = dataUser.createRandomTestUser();
SiteModel testSite = dataSite.usingUser(testUser).createPublicRandomSite();
FolderModel testFolder = dataContent.usingUser(testUser).usingSite(testSite).createFolder();
testContentFile = dataContent.usingUser(testUser).usingResource(testFolder)
.createContent(new FileModel("hotOuside", FileType.TEXT_PLAIN, FILE_CONTENT));
String authHeader = String.format("%s:%s", testUser.getUsername(), testUser.getPassword());
authHeaderEncoded = new String(Base64.encodeBase64(authHeader.getBytes()));
RestAssured.basePath = "";
restClient.configureRequestSpec().setBasePath(RestAssured.basePath);
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using short descriptor and attach short descriptor.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSShortAttachShort()
{
authenticateTestUser();
RestRequest request = RestRequest.simpleRequest(
HttpMethod.GET, downloadContentServletAttach + testContentFile.getNodeRef() + "/" + testContentFile.getName());
RestResponse response = restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.OK);
assertEquals(FILE_CONTENT, response.getResponse().body().asString());
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT);
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName()));
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using short descriptor and attach long descriptor.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSShortAttachLong()
{
authenticateTestUser();
String downloadContentServletAttachLong = "alfresco/d/attach/workspace/SpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentServletAttachLong + testContentFile.getNodeRef() + "/" + testContentFile.getName());
RestResponse response = restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.OK);
assertEquals(FILE_CONTENT, response.getResponse().body().asString());
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT);
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName()));
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using short descriptor and direct short descriptor.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSShortDirectShort()
{
authenticateTestUser();
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentServletDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName());
RestResponse response = restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.OK);
assertEquals(FILE_CONTENT, response.getResponse().body().asString());
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT);
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName()));
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using short descriptor and direct long descriptor.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSShortDirectLong()
{
authenticateTestUser();
String downloadContentServletDirectLong = "alfresco/d/direct/workspace/SpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentServletDirectLong + testContentFile.getNodeRef() + "/" + testContentFile.getName());
RestResponse response = restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.OK);
assertEquals(FILE_CONTENT, response.getResponse().body().asString());
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT);
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName()));
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using long descriptor and attach short descriptor.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSLongAttachShort()
{
authenticateTestUser();
String downloadContentLongServletAttach = "alfresco/download/a/workspace/SpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentLongServletAttach + testContentFile.getNodeRef() + "/" + testContentFile.getName());
RestResponse response = restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.OK);
assertEquals(FILE_CONTENT, response.getResponse().body().asString());
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT);
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName()));
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using long descriptor and attach long descriptor.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSLongAttachLong()
{
authenticateTestUser();
String downloadContentLongServletAttachLong = "alfresco/download/attach/workspace/SpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentLongServletAttachLong + testContentFile.getNodeRef() + "/" + testContentFile.getName());
RestResponse response = restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.OK);
assertEquals(FILE_CONTENT, response.getResponse().body().asString());
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT);
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName()));
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using long descriptor and direct short descriptor.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSLongDirectShort()
{
authenticateTestUser();
String downloadContentLongServletDirect = "alfresco/download/d/workspace/SpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentLongServletDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName());
RestResponse response = restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.OK);
assertEquals(FILE_CONTENT, response.getResponse().body().asString());
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT);
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName()));
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using long descriptor and direct long descriptor.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSLongDirectLong()
{
authenticateTestUser();
String downloadContentLongServletDirectLong = "alfresco/download/direct/workspace/SpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentLongServletDirectLong + testContentFile.getNodeRef() + "/" + testContentFile.getName());
RestResponse response = restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.OK);
assertEquals(FILE_CONTENT, response.getResponse().body().asString());
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT);
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName()));
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using short descriptor and attach short uppercase descriptor.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSShortAttachUppercaseShort()
{
authenticateTestUser();
String downloadContentAttachUppercase = "alfresco/d/A/workspace/SpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentAttachUppercase + testContentFile.getNodeRef() + "/" + testContentFile.getName());
RestResponse response = restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.OK);
assertEquals(FILE_CONTENT, response.getResponse().body().asString());
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT);
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName()));
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using short descriptor and direct short uppercase descriptor.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSShortDirectUppercaseShort()
{
authenticateTestUser();
String downloadContentDirectUppercase = "alfresco/d/D/workspace/SpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentDirectUppercase + testContentFile.getNodeRef() + "/" + testContentFile.getName());
RestResponse response = restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.OK);
assertEquals(FILE_CONTENT, response.getResponse().body().asString());
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, ATTACHMENT);
restClient.assertHeaderValueContains(CONTENT_DISPOSITION, String.format(FILENAME_HEADER, testContentFile.getName()));
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using attach without specifying {storeType}.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSAttachWithoutStoreType()
{
authenticateTestUser();
String downloadContentLessPathAttach = "alfresco/d/a/SpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentLessPathAttach + testContentFile.getNodeRef() + "/" + testContentFile.getName());
restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.INTERNAL_SERVER_ERROR);
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using direct without specifying {storeType}.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSDirectWithoutStoreType()
{
authenticateTestUser();
String downloadContentLessPathDirect = "alfresco/d/d/SpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentLessPathDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName());
restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.INTERNAL_SERVER_ERROR);
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using direct without specifying {storeType}.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSDirectWithInvalidStoreType()
{
authenticateTestUser();
String downloadContentLessPathDirect = "alfresco/download/d/badWorkspace/SpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentLessPathDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName());
restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.INTERNAL_SERVER_ERROR);
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using direct without specifying {storeType}.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSDirectWithInvalidStoreId()
{
authenticateTestUser();
String downloadContentLessPathDirect = "alfresco/download/d/workspace/badSpacesStore/";
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentLessPathDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName());
restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.INTERNAL_SERVER_ERROR);
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using attach without authentication.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSAttachWithoutAuthentication()
{
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentServletAttach + testContentFile.getNodeRef() + "/" + testContentFile.getName());
restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.UNAUTHORIZED);
}
@TestRail(section = { TestGroup.REST_API },
executionType = ExecutionType.REGRESSION,
description = "Verify DownloadContentServlet retrieve content using direct without authentication.")
@Test(groups = { TestGroup.REST_API, TestGroup.FULL, TestGroup.ENTERPRISE})
@Bug(id ="MNT-21602", status=Bug.Status.FIXED)
public void verifyDCSDirectWithoutAuthentication()
{
RestRequest request = RestRequest.simpleRequest(HttpMethod.GET,
downloadContentServletDirect + testContentFile.getNodeRef() + "/" + testContentFile.getName());
restClient.process(request);
restClient.assertStatusCodeIs(HttpStatus.UNAUTHORIZED);
}
private void authenticateTestUser()
{
restClient.configureRequestSpec()
.addHeader("Authorization", String.format("Basic %s", authHeaderEncoded))
.build();
}
}

View File

@@ -14,6 +14,7 @@
<package name="org.alfresco.rest.comments.*"/>
<package name="org.alfresco.rest.downloads.*"/>
<package name="org.alfresco.rest.favorites.*"/>
<package name="org.alfresco.rest.servlet.*"/>
</packages>
</test>
</suite>

View File

@@ -0,0 +1,128 @@
/*
* #%L
* Alfresco Repository WAR Community
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.web.app.servlet;
import org.alfresco.service.cmr.repository.StoreRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.URLDecoder;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.StringTokenizer;
/**
* Servlet responsible for streaming node content from the repo directly to the response stream.
* The appropriate mimetype is calculated based on filename extension.
* <p>
* The URL to the servlet should be generated thus:
* <pre>/alfresco/download/attach/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf</pre>
* or
* <pre>/alfresco/download/direct/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf</pre></p>
* <p>
* The 'attach' or 'direct' element is used to indicate whether to display the stream directly
* in the browser or download it as a file attachment.</p>
* <p>
* Since ACS 6.X, this Servlet redirects to GET /nodes/{nodeId}/content V1 REST API.
*
*
* @author Kevin Roast
* @author gavinc
*/
public class DownloadContentServlet extends HttpServlet
{
private static final long serialVersionUID = -576405943603122206L;
private static Log logger = LogFactory.getLog(DownloadContentServlet.class);
private static final String URL_ATTACH = "a";
private static final String URL_ATTACH_LONG = "attach";
private static final String URL_DIRECT = "d";
private static final String URL_DIRECT_LONG = "direct";
/**
* @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
*/
protected void doGet(final HttpServletRequest req, final HttpServletResponse res)
throws IOException
{
if (logger.isDebugEnabled())
{
String queryString = req.getQueryString();
logger.debug("Authenticating (GET) request to URL: " + req.getRequestURI() +
((queryString != null && queryString.length() > 0) ? ("?" + queryString) : ""));
}
// remove request context.
String requestURI = req.getRequestURI();
requestURI = requestURI.substring(req.getContextPath().length());
StringTokenizer t = new StringTokenizer(requestURI, "/");
int tokenCount = t.countTokens();
t.nextToken(); // skip servlet name
// expect a minimum of 6 URL tokens.
// /d/{attach|direct}/{storeType}/{storeId}/{nodeId}/{nodeName}
if(tokenCount < 6)
{
throw new IllegalArgumentException("Download URL did not contain all required args: " + requestURI);
}
// attachment mode (either 'attach' or 'direct')
String attachToken = t.nextToken();
boolean isAttachment = URL_ATTACH.equalsIgnoreCase(attachToken) || URL_ATTACH_LONG.equalsIgnoreCase(attachToken);
boolean isDirect = URL_DIRECT.equalsIgnoreCase(attachToken) || URL_DIRECT_LONG.equalsIgnoreCase(attachToken);
if (!(isAttachment || isDirect))
{
throw new IllegalArgumentException("Attachment mode is not properly specified: " + requestURI);
}
// allow only nodes from workspace://SpaceStore/ storeRef
StoreRef storeRef = new StoreRef(URLDecoder.decode(t.nextToken()), URLDecoder.decode(t.nextToken()));
boolean isWorkspaceStoreType = storeRef.getProtocol().equalsIgnoreCase("workspace");
boolean isSpacesStoreStoreId = storeRef.getIdentifier().equalsIgnoreCase("SpacesStore");
if (!isWorkspaceStoreType || !isSpacesStoreStoreId)
{
throw new IllegalArgumentException("Servlet accepts only nodes from workspace://SpaceStore/ storeRef: " + requestURI);
}
String nodeId = URLDecoder.decode(t.nextToken());
// build redirect URL to V1 GET /nodes/{nodeId}/content
String redirectUrl = String
.format("%s/api/-default-/public/alfresco/versions/1/nodes/%s/content?attachment=%b",
req.getContextPath(), nodeId, isAttachment);
if (logger.isDebugEnabled())
{
logger.debug("Request redirected to URL: " + redirectUrl);
}
res.sendRedirect(redirectUrl);
}
}

View File

@@ -243,6 +243,10 @@
</listener>
<!-- Enterprise listener placeholder -->
<servlet>
<servlet-name>downloadContent</servlet-name>
<servlet-class>org.alfresco.web.app.servlet.DownloadContentServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>WebDAV</servlet-name>
@@ -384,6 +388,16 @@
<!-- Enterprise servlet placeholder -->
<servlet-mapping>
<servlet-name>downloadContent</servlet-name>
<url-pattern>/download/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>downloadContent</servlet-name>
<url-pattern>/d/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>WebDAV</servlet-name>
<url-pattern>/webdav/*</url-pattern>