Java tutorial
/* * 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.jackrabbit.webdav.server; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import junit.framework.TestCase; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.HeadMethod; import org.apache.commons.httpclient.methods.PutMethod; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.MultiStatus; import org.apache.jackrabbit.webdav.MultiStatusResponse; import org.apache.jackrabbit.webdav.bind.BindConstants; import org.apache.jackrabbit.webdav.bind.BindInfo; import org.apache.jackrabbit.webdav.bind.ParentElement; import org.apache.jackrabbit.webdav.bind.RebindInfo; import org.apache.jackrabbit.webdav.bind.UnbindInfo; import org.apache.jackrabbit.webdav.client.methods.BindMethod; import org.apache.jackrabbit.webdav.client.methods.DavMethodBase; import org.apache.jackrabbit.webdav.client.methods.DeleteMethod; import org.apache.jackrabbit.webdav.client.methods.MkColMethod; import org.apache.jackrabbit.webdav.client.methods.MoveMethod; import org.apache.jackrabbit.webdav.client.methods.OptionsMethod; import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; import org.apache.jackrabbit.webdav.client.methods.RebindMethod; import org.apache.jackrabbit.webdav.client.methods.UnbindMethod; import org.apache.jackrabbit.webdav.client.methods.VersionControlMethod; import org.apache.jackrabbit.webdav.property.DavProperty; import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * Test cases for WebDAV BIND functionality (see <a href="http://greenbytes.de/tech/webdav/rfc5842.html">RFC 5842</a> * <p> * Required system properties: * <ul> * <li>webdav.test.url</li> * <li>webdav.test.username</li> * <li>webdav.test.password</li> * </ul> */ public class BindTest extends TestCase { private String root; private URI uri; private String username, password; private HttpClient client; protected void setUp() throws Exception { this.uri = URI.create(System.getProperty("webdav.test.url")); this.root = this.uri.toASCIIString(); if (!this.root.endsWith("/")) { this.root += "/"; } this.username = System.getProperty(("webdav.test.username"), ""); this.password = System.getProperty(("webdav.test.password"), ""); this.client = new HttpClient(); this.client.getState().setCredentials(new AuthScope(this.uri.getHost(), this.uri.getPort()), new UsernamePasswordCredentials(this.username, this.password)); super.setUp(); } protected void tearDown() throws Exception { super.tearDown(); } // http://greenbytes.de/tech/webdav/rfc5842.html#rfc.section.8.1 public void testOptions() throws HttpException, IOException { OptionsMethod options = new OptionsMethod(this.uri.toASCIIString()); int status = this.client.executeMethod(options); assertEquals(200, status); List allow = Arrays.asList(options.getAllowedMethods()); assertTrue("DAV header should include 'bind' feature", options.hasComplianceClass("bind")); assertTrue("Allow header should include BIND method", allow.contains("BIND")); assertTrue("Allow header should include REBIND method", allow.contains("REBIND")); assertTrue("Allow header should include UNBIND method", allow.contains("UNBIND")); } // create test resource, make it referenceable, check resource id, move resource, check again public void testResourceId() throws HttpException, IOException, DavException, URISyntaxException { String testcol = this.root + "testResourceId/"; String testuri1 = testcol + "bindtest1"; String testuri2 = testcol + "bindtest2"; int status; try { MkColMethod mkcol = new MkColMethod(testcol); status = this.client.executeMethod(mkcol); assertEquals(201, status); PutMethod put = new PutMethod(testuri1); put.setRequestEntity(new StringRequestEntity("foo", "text/plain", "UTF-8")); status = this.client.executeMethod(put); assertEquals(201, status); // enabling version control always makes the resource referenceable VersionControlMethod versioncontrol = new VersionControlMethod(testuri1); status = this.client.executeMethod(versioncontrol); assertTrue("status: " + status, status == 200 || status == 201); URI resourceId = getResourceId(testuri1); MoveMethod move = new MoveMethod(testuri1, testuri2, true); status = this.client.executeMethod(move); move.getResponseBodyAsString(); assertEquals(201, status); URI resourceId2 = getResourceId(testuri2); assertEquals(resourceId, resourceId2); } finally { DeleteMethod delete = new DeleteMethod(testcol); status = this.client.executeMethod(delete); assertTrue("status: " + status, status == 200 || status == 204); } } // utility methods // see http://greenbytes.de/tech/webdav/rfc5842.html#rfc.section.3.1 private URI getResourceId(String uri) throws IOException, DavException, URISyntaxException { DavPropertyNameSet names = new DavPropertyNameSet(); names.add(BindConstants.RESOURCEID); PropFindMethod propfind = new PropFindMethod(uri, names, 0); int status = this.client.executeMethod(propfind); assertEquals(207, status); MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(); MultiStatusResponse[] responses = multistatus.getResponses(); assertEquals(1, responses.length); DavProperty resourceId = responses[0].getProperties(200).get(BindConstants.RESOURCEID); assertNotNull(resourceId); assertTrue(resourceId.getValue() instanceof Element); Element href = (Element) resourceId.getValue(); assertEquals("href", href.getLocalName()); String text = getUri(href); URI resid = new URI(text); return resid; } private DavProperty getParentSet(String uri) throws IOException, DavException, URISyntaxException { DavPropertyNameSet names = new DavPropertyNameSet(); names.add(BindConstants.PARENTSET); PropFindMethod propfind = new PropFindMethod(uri, names, 0); int status = this.client.executeMethod(propfind); assertEquals(207, status); MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(); MultiStatusResponse[] responses = multistatus.getResponses(); assertEquals(1, responses.length); DavProperty parentset = responses[0].getProperties(200).get(BindConstants.PARENTSET); assertNotNull(parentset); return parentset; } public void testSimpleBind() throws Exception { String testcol = this.root + "testSimpleBind/"; String subcol1 = testcol + "bindtest1/"; String testres1 = subcol1 + "res1"; String subcol2 = testcol + "bindtest2/"; String testres2 = subcol2 + "res2"; int status; try { MkColMethod mkcol = new MkColMethod(testcol); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol1); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol2); status = this.client.executeMethod(mkcol); assertEquals(201, status); //create new resource R with path bindtest1/res1 PutMethod put = new PutMethod(testres1); put.setRequestEntity(new StringRequestEntity("foo", "text/plain", "UTF-8")); status = this.client.executeMethod(put); assertEquals(201, status); //create new binding of R with path bindtest2/res2 DavMethodBase bind = new BindMethod(subcol2, new BindInfo(testres1, "res2")); status = this.client.executeMethod(bind); assertEquals(201, status); //check if both bindings report the same DAV:resource-id assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); //compare representations retrieved with both paths GetMethod get = new GetMethod(testres1); status = this.client.executeMethod(get); assertEquals(200, status); assertEquals("foo", get.getResponseBodyAsString()); get = new GetMethod(testres2); status = this.client.executeMethod(get); assertEquals(200, status); assertEquals("foo", get.getResponseBodyAsString()); //modify R using the new path put = new PutMethod(testres2); put.setRequestEntity(new StringRequestEntity("bar", "text/plain", "UTF-8")); status = this.client.executeMethod(put); assertTrue("status: " + status, status == 200 || status == 204); //compare representations retrieved with both paths get = new GetMethod(testres1); status = this.client.executeMethod(get); assertEquals(200, status); assertEquals("bar", get.getResponseBodyAsString()); get = new GetMethod(testres2); status = this.client.executeMethod(get); assertEquals(200, status); assertEquals("bar", get.getResponseBodyAsString()); } finally { DeleteMethod delete = new DeleteMethod(testcol); status = this.client.executeMethod(delete); assertTrue("status: " + status, status == 200 || status == 204); } } public void testRebind() throws Exception { String testcol = this.root + "testRebind/"; String subcol1 = testcol + "bindtest1/"; String testres1 = subcol1 + "res1"; String subcol2 = testcol + "bindtest2/"; String testres2 = subcol2 + "res2"; int status; try { MkColMethod mkcol = new MkColMethod(testcol); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol1); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol2); status = this.client.executeMethod(mkcol); assertEquals(201, status); //create new resource R with path bindtest1/res1 PutMethod put = new PutMethod(testres1); put.setRequestEntity(new StringRequestEntity("foo", "text/plain", "UTF-8")); status = this.client.executeMethod(put); assertEquals(201, status); // enabling version control always makes the resource referenceable VersionControlMethod versioncontrol = new VersionControlMethod(testres1); status = this.client.executeMethod(versioncontrol); assertTrue("status: " + status, status == 200 || status == 201); URI r1 = this.getResourceId(testres1); GetMethod get = new GetMethod(testres1); status = this.client.executeMethod(get); assertEquals(200, status); assertEquals("foo", get.getResponseBodyAsString()); //rebind R with path bindtest2/res2 DavMethodBase rebind = new RebindMethod(subcol2, new RebindInfo(testres1, "res2")); status = this.client.executeMethod(rebind); assertEquals(201, status); URI r2 = this.getResourceId(testres2); get = new GetMethod(testres2); status = this.client.executeMethod(get); assertEquals(200, status); assertEquals("foo", get.getResponseBodyAsString()); //make sure that rebind did not change the resource-id assertEquals(r1, r2); //verify that the initial binding is gone HeadMethod head = new HeadMethod(testres1); status = this.client.executeMethod(head); assertEquals(404, status); } finally { DeleteMethod delete = new DeleteMethod(testcol); status = this.client.executeMethod(delete); assertTrue("status: " + status, status == 200 || status == 204); } } public void testBindOverwrite() throws Exception { String testcol = this.root + "testSimpleBind/"; String subcol1 = testcol + "bindtest1/"; String testres1 = subcol1 + "res1"; String subcol2 = testcol + "bindtest2/"; String testres2 = subcol2 + "res2"; int status; try { MkColMethod mkcol = new MkColMethod(testcol); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol1); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol2); status = this.client.executeMethod(mkcol); assertEquals(201, status); //create new resource R with path bindtest1/res1 PutMethod put = new PutMethod(testres1); put.setRequestEntity(new StringRequestEntity("foo", "text/plain", "UTF-8")); status = this.client.executeMethod(put); assertEquals(201, status); //create new resource R' with path bindtest2/res2 put = new PutMethod(testres2); put.setRequestEntity(new StringRequestEntity("bar", "text/plain", "UTF-8")); status = this.client.executeMethod(put); assertEquals(201, status); //try to create new binding of R with path bindtest2/res2 and Overwrite:F DavMethodBase bind = new BindMethod(subcol2, new BindInfo(testres1, "res2")); bind.addRequestHeader(new Header("Overwrite", "F")); status = this.client.executeMethod(bind); assertEquals(412, status); //verify that bindtest2/res2 still points to R' GetMethod get = new GetMethod(testres2); status = this.client.executeMethod(get); assertEquals(200, status); assertEquals("bar", get.getResponseBodyAsString()); //create new binding of R with path bindtest2/res2 bind = new BindMethod(subcol2, new BindInfo(testres1, "res2")); status = this.client.executeMethod(bind); assertTrue("status: " + status, status == 200 || status == 204); //verify that bindtest2/res2 now points to R get = new GetMethod(testres2); status = this.client.executeMethod(get); assertEquals(200, status); assertEquals("foo", get.getResponseBodyAsString()); //verify that the initial binding is still there HeadMethod head = new HeadMethod(testres1); status = this.client.executeMethod(head); assertEquals(200, status); } finally { DeleteMethod delete = new DeleteMethod(testcol); status = this.client.executeMethod(delete); assertTrue("status: " + status, status == 200 || status == 204); } } public void testRebindOverwrite() throws Exception { String testcol = this.root + "testSimpleBind/"; String subcol1 = testcol + "bindtest1/"; String testres1 = subcol1 + "res1"; String subcol2 = testcol + "bindtest2/"; String testres2 = subcol2 + "res2"; int status; try { MkColMethod mkcol = new MkColMethod(testcol); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol1); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol2); status = this.client.executeMethod(mkcol); assertEquals(201, status); //create new resource R with path testSimpleBind/bindtest1/res1 PutMethod put = new PutMethod(testres1); put.setRequestEntity(new StringRequestEntity("foo", "text/plain", "UTF-8")); status = this.client.executeMethod(put); assertEquals(201, status); // enabling version control always makes the resource referenceable VersionControlMethod versioncontrol = new VersionControlMethod(testres1); status = this.client.executeMethod(versioncontrol); assertTrue("status: " + status, status == 200 || status == 201); //create new resource R' with path testSimpleBind/bindtest2/res2 put = new PutMethod(testres2); put.setRequestEntity(new StringRequestEntity("bar", "text/plain", "UTF-8")); status = this.client.executeMethod(put); assertEquals(201, status); //try rebind R with path testSimpleBind/bindtest2/res2 and Overwrite:F RebindMethod rebind = new RebindMethod(subcol2, new RebindInfo(testres1, "res2")); rebind.addRequestHeader(new Header("Overwrite", "F")); status = this.client.executeMethod(rebind); assertEquals(412, status); //verify that testSimpleBind/bindtest2/res2 still points to R' GetMethod get = new GetMethod(testres2); status = this.client.executeMethod(get); assertEquals(200, status); assertEquals("bar", get.getResponseBodyAsString()); //rebind R with path testSimpleBind/bindtest2/res2 rebind = new RebindMethod(subcol2, new RebindInfo(testres1, "res2")); status = this.client.executeMethod(rebind); assertTrue("status: " + status, status == 200 || status == 204); //verify that testSimpleBind/bindtest2/res2 now points to R get = new GetMethod(testres2); status = this.client.executeMethod(get); assertEquals(200, status); assertEquals("foo", get.getResponseBodyAsString()); //verify that the initial binding is gone HeadMethod head = new HeadMethod(testres1); status = this.client.executeMethod(head); assertEquals(404, status); } finally { DeleteMethod delete = new DeleteMethod(testcol); status = this.client.executeMethod(delete); assertTrue("status: " + status, status == 200 || status == 204); } } public void testParentSet() throws Exception { String testcol = this.root + "testParentSet/"; String subcol1 = testcol + "bindtest1/"; String testres1 = subcol1 + "res1"; String subcol2 = testcol + "bindtest2/"; String testres2 = subcol2 + "res2"; int status; try { MkColMethod mkcol = new MkColMethod(testcol); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol1); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol2); status = this.client.executeMethod(mkcol); assertEquals(201, status); //create new resource R with path testSimpleBind/bindtest1/res1 PutMethod put = new PutMethod(testres1); put.setRequestEntity(new StringRequestEntity("foo", "text/plain", "UTF-8")); status = this.client.executeMethod(put); assertEquals(201, status); //create new binding of R with path testSimpleBind/bindtest2/res2 DavMethodBase bind = new BindMethod(subcol2, new BindInfo(testres1, "res2")); status = this.client.executeMethod(bind); assertEquals(201, status); //check if both bindings report the same DAV:resource-id assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); //verify values of parent-set properties List hrefs1 = new ArrayList(); List segments1 = new ArrayList(); List hrefs2 = new ArrayList(); List segments2 = new ArrayList(); Object ps1 = this.getParentSet(testres1).getValue(); Object ps2 = this.getParentSet(testres2).getValue(); assertTrue(ps1 instanceof List); assertTrue(ps2 instanceof List); List plist1 = (List) ps1; List plist2 = (List) ps2; assertEquals(2, plist1.size()); assertEquals(2, plist2.size()); for (int k = 0; k < 2; k++) { Object pObj1 = plist1.get(k); Object pObj2 = plist2.get(k); assertTrue(pObj1 instanceof Element); assertTrue(pObj2 instanceof Element); ParentElement p1 = ParentElement.createFromXml((Element) pObj1); ParentElement p2 = ParentElement.createFromXml((Element) pObj2); hrefs1.add(p1.getHref()); hrefs2.add(p2.getHref()); segments1.add(p1.getSegment()); segments2.add(p2.getSegment()); } Collections.sort(hrefs1); Collections.sort(hrefs2); Collections.sort(segments1); Collections.sort(segments2); assertEquals(hrefs1, hrefs2); assertEquals(segments1, segments2); } finally { DeleteMethod delete = new DeleteMethod(testcol); status = this.client.executeMethod(delete); assertTrue("status: " + status, status == 200 || status == 204); } } public void testBindCollections() throws Exception { String testcol = this.root + "testBindCollections/"; String a1 = testcol + "a1/"; String b1 = a1 + "b1/"; String c1 = b1 + "c1/"; String x1 = c1 + "x1"; String a2 = testcol + "a2/"; String b2 = a2 + "b2/"; String c2 = b2 + "c2/"; String x2 = c2 + "x2"; int status; try { MkColMethod mkcol = new MkColMethod(testcol); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(a1); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(a2); status = this.client.executeMethod(mkcol); assertEquals(201, status); //create collection resource C mkcol = new MkColMethod(b1); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(c1); status = this.client.executeMethod(mkcol); assertEquals(201, status); //create plain resource R PutMethod put = new PutMethod(x1); put.setRequestEntity(new StringRequestEntity("foo", "text/plain", "UTF-8")); status = this.client.executeMethod(put); assertEquals(201, status); //create new binding of C with path a2/b2 DavMethodBase bind = new BindMethod(a2, new BindInfo(b1, "b2")); status = this.client.executeMethod(bind); assertEquals(201, status); //check if both bindings report the same DAV:resource-id assertEquals(this.getResourceId(b1), this.getResourceId(b2)); mkcol = new MkColMethod(c2); status = this.client.executeMethod(mkcol); assertEquals(201, status); //create new binding of R with path a2/b2/c2/r2 bind = new BindMethod(c2, new BindInfo(x1, "x2")); status = this.client.executeMethod(bind); assertEquals(201, status); //check if both bindings report the same DAV:resource-id assertEquals(this.getResourceId(x1), this.getResourceId(x2)); //verify different path alternatives URI rid = this.getResourceId(x1); assertEquals(rid, this.getResourceId(x2)); assertEquals(rid, this.getResourceId(testcol + "a2/b2/c1/x1")); assertEquals(rid, this.getResourceId(testcol + "a1/b1/c2/x2")); Object ps = this.getParentSet(x1).getValue(); assertTrue(ps instanceof List); assertEquals(2, ((List) ps).size()); ps = this.getParentSet(x2).getValue(); assertTrue(ps instanceof List); assertEquals(2, ((List) ps).size()); } finally { DeleteMethod delete = new DeleteMethod(testcol); status = this.client.executeMethod(delete); assertTrue("status: " + status, status == 200 || status == 204); } } //will fail until <https://issues.apache.org/jira/browse/JCR-1773> is fixed public void testUnbind() throws Exception { String testcol = this.root + "testUnbind/"; String subcol1 = testcol + "bindtest1/"; String testres1 = subcol1 + "res1"; String subcol2 = testcol + "bindtest2/"; String testres2 = subcol2 + "res2"; int status; try { MkColMethod mkcol = new MkColMethod(testcol); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol1); status = this.client.executeMethod(mkcol); assertEquals(201, status); mkcol = new MkColMethod(subcol2); status = this.client.executeMethod(mkcol); assertEquals(201, status); //create new resource R with path testSimpleBind/bindtest1/res1 PutMethod put = new PutMethod(testres1); put.setRequestEntity(new StringRequestEntity("foo", "text/plain", "UTF-8")); status = this.client.executeMethod(put); assertEquals(201, status); //create new binding of R with path testSimpleBind/bindtest2/res2 DavMethodBase bind = new BindMethod(subcol2, new BindInfo(testres1, "res2")); status = this.client.executeMethod(bind); assertEquals(201, status); //check if both bindings report the same DAV:resource-id assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); //remove new path UnbindMethod unbind = new UnbindMethod(subcol2, new UnbindInfo("res2")); status = this.client.executeMethod(unbind); assertTrue("status: " + status, status == 200 || status == 204); //verify that the new binding is gone HeadMethod head = new HeadMethod(testres2); status = this.client.executeMethod(head); assertEquals(404, status); //verify that the initial binding is still there head = new HeadMethod(testres1); status = this.client.executeMethod(head); assertEquals(200, status); } finally { DeleteMethod delete = new DeleteMethod(testcol); status = this.client.executeMethod(delete); assertTrue("status: " + status, status == 200 || status == 204); } } private String getUri(Element href) { String s = ""; for (Node c = href.getFirstChild(); c != null; c = c.getNextSibling()) { if (c.getNodeType() == Node.TEXT_NODE) { s += c.getNodeValue(); } } return s; } }