/******************************************************************************* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.wink.webdav.server; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.ws.rs.core.MediaType; import javax.xml.namespace.QName; import org.apache.wink.common.http.HttpHeadersEx; import org.apache.wink.common.http.HttpStatus; import org.apache.wink.server.internal.servlet.MockServletInvocationTest; import org.apache.wink.test.mock.MockHttpServletRequestWrapper; import org.apache.wink.webdav.WebDAVConstants; import org.apache.wink.webdav.WebDAVHeaders; import org.apache.wink.webdav.WebDAVMethod; import org.apache.wink.webdav.model.Activelock; import org.apache.wink.webdav.model.Exclusive; import org.apache.wink.webdav.model.Lockinfo; import org.apache.wink.webdav.model.Lockscope; import org.apache.wink.webdav.model.Locktype; import org.apache.wink.webdav.model.Multistatus; import org.apache.wink.webdav.model.Prop; import org.apache.wink.webdav.model.Propfind; import org.apache.wink.webdav.model.Propstat; import org.apache.wink.webdav.model.Response; import org.apache.wink.webdav.model.WebDAVModelHelper; import org.apache.wink.webdav.model.Write; import org.junit.Assert; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; public abstract class AbstractWebDAVResourcesTest extends MockServletInvocationTest { public static final HttpStatus[] COLLECTION_OKS = {HttpStatus.OK, HttpStatus.OK, HttpStatus.OK }; public static final HttpStatus[] DOCUMENT_OKS = {HttpStatus.OK, HttpStatus.OK, HttpStatus.OK, HttpStatus.OK }; public static QName[] PROPERTIES_DOCUMENT = new QName[] { WebDAVConstants.PROPERTY_CREATIONDATE, WebDAVConstants.PROPERTY_DISPLAYNAME, WebDAVConstants.PROPERTY_GETLASTMODIFIED, WebDAVConstants.PROPERTY_RESOURCETYPE}; public static QName[] PROPERTIES_COLLECTION = new QName[] { WebDAVConstants.PROPERTY_RESOURCETYPE, WebDAVConstants.PROPERTY_DISPLAYNAME, WebDAVConstants.PROPERTY_GETLASTMODIFIED }; protected static MockHttpServletRequest constructPropfindRequest(Propfind propfind, String requestURI, int depth) throws IOException { MockHttpServletRequest mockRequest = new MockHttpServletRequestWrapper() { public String getPathTranslated() { return null; // prevent Spring to resolve the file on the file // system which fails } }; // headers mockRequest.setMethod(WebDAVMethod.PROPFIND.name()); mockRequest.setRequestURI(requestURI); mockRequest.setContentType(MediaType.APPLICATION_XML); if (depth >= 0) { mockRequest.addHeader(WebDAVHeaders.DEPTH, String.valueOf(depth)); } // body StringWriter writer = new StringWriter(); Propfind.marshal(propfind, writer); mockRequest.setContent(writer.toString().getBytes()); return mockRequest; } protected static Multistatus getMultistatus(MockHttpServletResponse response) throws IOException { // headers Assert.assertEquals(HttpStatus.MULTI_STATUS.getCode(), response.getStatus()); MediaType mediaType = MediaType.valueOf(response.getContentType()); // we can't clear MediaType params due to UnsupportedOperationException on the collection, so... Assert.assertEquals(MediaType.valueOf(MediaType.APPLICATION_XML_TYPE.toString()), mediaType); // body String responseContent = response.getContentAsString(); StringReader reader = new StringReader(responseContent); Multistatus multistatus = Multistatus.unmarshal(reader); return multistatus; } protected Multistatus propfind(Propfind propfind, String requestURI, int depth) throws Exception { MockHttpServletRequest request = constructPropfindRequest(propfind, requestURI, depth); MockHttpServletResponse response = invoke(request); return getMultistatus(response); } private static void checkProperties(Response response, QName[] propertyNames, HttpStatus[] statuses) { int totalCovered = 0; for (Propstat propstat : response.getPropstat()) { int statusCode = propstat.getStatusCode(); Set<QName> expectedPropnames = new HashSet<QName>(); for (int i = 0; i < statuses.length; ++i) { if (statuses[i].getCode() == statusCode) { expectedPropnames.add(propertyNames[i]); } } totalCovered += expectedPropnames.size(); Prop prop = propstat.getProp(); Set<QName> propnames = WebDAVModelHelper.extractPropertyNames(prop, new HashSet<QName>()); Assert.assertEquals(expectedPropnames.size(), propnames.size()); for (QName name : expectedPropnames) { Assert.assertTrue(propnames.contains(name)); } } Assert.assertEquals(propertyNames.length, totalCovered); } protected static void checkCollectionPropertyNames(Response response) { checkProperties(response, PROPERTIES_COLLECTION, COLLECTION_OKS); } protected static void checkCollectionProperties(Response response, String name) { // check it contains all collection properties with OK status checkCollectionPropertyNames(response); Prop prop = response.getPropstat().get(0).getProp(); // check name property Assert.assertEquals(name, prop.getDisplayname().getValue()); // check the resource type property Assert.assertTrue(prop.getResourcetype().getCollection() != null); } protected static void checkRootCollectionProperties(Response response, String name) { // check it contains the root collection properties with OK status HttpStatus[] rootStatuses = {HttpStatus.OK, HttpStatus.OK, HttpStatus.NOT_FOUND}; checkProperties(response, PROPERTIES_COLLECTION, rootStatuses); Prop prop = response.getPropstat().get(0).getProp(); // check name property String displayName = ""; if (prop.getDisplayname().getValue() != null) { displayName = prop.getDisplayname().getValue(); } Assert.assertEquals(name, displayName); // check the resource type property Assert.assertTrue(prop.getResourcetype().getCollection() != null); } protected static void checkDocumentPropertyNames(Response response) { checkProperties(response, PROPERTIES_DOCUMENT, DOCUMENT_OKS); } protected static void checkDocumentProperties(Response response, String name) { // check it contains all document properties with OK status checkDocumentPropertyNames(response); Prop prop = response.getPropstat().get(0).getProp(); // check name property Assert.assertEquals(name, prop.getDisplayname().getValue()); // check the resource type property Assert.assertFalse(prop.getResourcetype().getCollection() != null); } protected void checkOptions(String path, boolean alsoLock) throws Exception { // request MockHttpServletRequest request = new MockHttpServletRequest() { public String getPathTranslated() { return null; // prevent Spring to resolve the file on the file // system which fails } }; request.setMethod("OPTIONS"); request.setRequestURI(path); MockHttpServletResponse response = invoke(request); // response Assert.assertEquals(HttpStatus.OK.getCode(), response.getStatus()); Assert.assertEquals("1", response.getHeader(WebDAVHeaders.DAV)); Assert.assertEquals("DAV", response.getHeader(WebDAVHeaders.MS_AUTHOR_VIA)); // check allow - must contain OPTIONS, PROPFIND, LOCK String allowStr = (String)response.getHeader(HttpHeadersEx.ALLOW); List<?> allows = Arrays.asList(allowStr.split("\\s*,\\s*")); Assert.assertTrue(allows.contains("OPTIONS")); Assert.assertTrue(allows.contains(WebDAVMethod.PROPFIND.name())); if (alsoLock) { Assert.assertTrue(allows.contains(WebDAVMethod.LOCK.name())); } else { Assert.assertFalse(allows.contains(WebDAVMethod.LOCK.name())); } } protected void checkLockAndUnlock(String path) throws Exception { // lock request MockHttpServletRequest request = new MockHttpServletRequest() { public String getPathTranslated() { return null; // prevent Spring to resolve the file on the file // system which fails } }; request.setMethod(WebDAVMethod.LOCK.name()); request.setRequestURI(path); request.setContentType(MediaType.APPLICATION_XML); Lockinfo lockinfo = new Lockinfo(); Lockscope lockscope = new Lockscope(); lockscope.setExclusive(new Exclusive()); lockinfo.setLockscope(lockscope); Locktype locktype = new Locktype(); locktype.setWrite(new Write()); lockinfo.setLocktype(locktype); StringWriter writer = new StringWriter(); WebDAVModelHelper.marshal(WebDAVModelHelper.createMarshaller(), lockinfo, writer, "lockinfo"); request.setContent(writer.toString().getBytes()); MockHttpServletResponse response = invoke(request); // lock response Assert.assertEquals(HttpStatus.OK.getCode(), response.getStatus()); MediaType mediaType = MediaType.valueOf(response.getContentType()); // we can't clear MediaType params due to UnsupportedOperationException on the collection, so... Assert.assertEquals(MediaType.valueOf(MediaType.APPLICATION_XML_TYPE.toString()), mediaType); StringReader reader = new StringReader(response.getContentAsString()); Prop prop = WebDAVModelHelper.unmarshal(WebDAVModelHelper.createUnmarshaller(), reader, Prop.class, "prop"); List<Activelock> activelocks = prop.getLockdiscovery().getActivelock(); Assert.assertNotNull(activelocks); Assert.assertEquals(1, activelocks.size()); Assert.assertNotNull(activelocks.get(0).getLocktype().getWrite()); Assert.assertNotNull(activelocks.get(0).getLockscope().getExclusive()); Assert.assertEquals("0", activelocks.get(0).getDepth()); // unlock request request = new MockHttpServletRequest() { public String getPathTranslated() { return null; // prevent Spring to resolve the file on the file // system which fails } }; request.setMethod(WebDAVMethod.UNLOCK.name()); request.setRequestURI(path); response = invoke(request); // lock response Assert.assertEquals(HttpStatus.NO_CONTENT.getCode(), response.getStatus()); } }