Java tutorial
// vi: set ts=3 sw=3: /* * $Header$ * $Revision: 208523 $ * $Date: 2005-02-22 00:33:03 +0800 (Tue, 22 Feb 2005) $ * ======================================================================== * Copyright 2004 The Apache Software Foundation * * 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 org.apache.webdav.ant; import java.io.IOException; import java.io.InputStream; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Enumeration; import java.util.Locale; import java.util.Stack; import java.util.Vector; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.HttpURL; import org.apache.commons.httpclient.HttpsURL; import org.apache.commons.httpclient.URIException; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.HeadMethod; import org.apache.commons.httpclient.methods.PutMethod; import org.apache.tools.ant.BuildException; import org.apache.webdav.lib.Property; import org.apache.webdav.lib.PropertyName; import org.apache.webdav.lib.ResponseEntity; import org.apache.webdav.lib.WebdavException; import org.apache.webdav.lib.methods.CopyMethod; import org.apache.webdav.lib.methods.LockMethod; import org.apache.webdav.lib.methods.MkcolMethod; import org.apache.webdav.lib.methods.MoveMethod; import org.apache.webdav.lib.methods.PropFindMethod; import org.apache.webdav.lib.methods.UnlockMethod; import org.apache.webdav.lib.properties.ResourceTypeProperty; import org.apache.webdav.lib.util.WebdavStatus; /** */ public class Utils { public static final String DAV_NAMESPACE = "DAV:"; public static final PropertyName DISPLAYNAME = new PropertyName(DAV_NAMESPACE, "displayname"); public static final PropertyName GETLASTMODIFIED = new PropertyName(DAV_NAMESPACE, "getlastmodified"); public static final DateFormat GETLASTMODIFIED_FORMAT = new SimpleDateFormat("EEE, d MMM yyyy kk:mm:ss z", Locale.US); public static final PropertyName RESOURCETYPE = new PropertyName(DAV_NAMESPACE, "resourcetype"); /** * Lookup for given property in a propfind response. * @param propFind the method, must always be rxecuted * @param name * @param path path of the item for which the property is searched for * @return the property of <code>null</code> if not found */ public static Property findProperty(PropFindMethod propFind, PropertyName name, String path) { Enumeration e = propFind.getResponseProperties(path); Property p = findProperty(e, name); // a collection requested as /a/col/path/ may be as // /a/col/path in the response if (p == null && path.endsWith("/")) { e = propFind.getResponseProperties(path.substring(0, path.length() - 1)); p = findProperty(e, name); } return p; } /** * Searches in the enumeration of Propery objects for a property with the * given name. * @param e enumeration of Property objects. * @param name * @return the property searched for of <code>null</code> if not found. */ public static Property findProperty(Enumeration e, PropertyName name) { while (e.hasMoreElements()) { Property p = (Property) e.nextElement(); if (p.getNamespaceURI().equals(name.getNamespaceURI()) && p.getLocalName().equals(name.getLocalName())) { return p; } } return null; } /** * Returns <code>true</code> if the resource given as URL does exist. * @param client * @param httpURL * @return <code>true</code>if the resource exists * @throws IOException * @throws HttpException */ public static boolean resourceExists(HttpClient client, HttpURL httpURL) throws IOException, HttpException { HeadMethod head = new HeadMethod(httpURL.getEscapedURI()); head.setFollowRedirects(true); int status = client.executeMethod(head); switch (status) { case WebdavStatus.SC_OK: return true; case WebdavStatus.SC_NOT_FOUND: return false; default: HttpException ex = new HttpException(); ex.setReasonCode(status); ex.setReason(head.getStatusText()); throw ex; } } public static boolean collectionExists(HttpClient client, HttpURL httpURL) throws IOException, HttpException { Vector props = new Vector(1); props.add(RESOURCETYPE); PropFindMethod propFind = new PropFindMethod(httpURL.getEscapedURI(), 0, PropFindMethod.BY_NAME); propFind.setFollowRedirects(true); propFind.setPropertyNames(props.elements()); propFind.setAssertHrefsArePathes(true); propFind.setDecodeResponseHrefs("UTF-8"); int status = client.executeMethod(propFind); switch (status) { case WebdavStatus.SC_MULTI_STATUS: Property p = findProperty(propFind, RESOURCETYPE, httpURL.getPath()); if (p instanceof ResourceTypeProperty) { return ((ResourceTypeProperty) p).isCollection(); } else { throw new WebdavException("PROPFFIND does not return resourcetype"); } case WebdavStatus.SC_NOT_FOUND: return false; default: HttpException ex = new HttpException(); ex.setReasonCode(status); ex.setReason(propFind.getStatusText()); throw ex; } } public static long getLastModified(HttpClient client, HttpURL url) throws IOException, HttpException { Vector props = new Vector(1); props.add(GETLASTMODIFIED); PropFindMethod propFind = new PropFindMethod(url.getEscapedURI(), 0); propFind.setPropertyNames(props.elements()); propFind.setFollowRedirects(true); propFind.setAssertHrefsArePathes(true); propFind.setDecodeResponseHrefs("UTF-8"); int status = client.executeMethod(propFind); switch (status) { case WebdavStatus.SC_MULTI_STATUS: Property p = findProperty(propFind, GETLASTMODIFIED, url.getPath()); if (p != null) { try { Date d = GETLASTMODIFIED_FORMAT.parse(p.getPropertyAsString()); return d.getTime(); } catch (ParseException e) { throw new HttpException("Invalid lastmodified property: " + p.getPropertyAsString()); } } throw new HttpException("PROPFIND does not return lastmodified."); default: HttpException ex = new HttpException(); ex.setReasonCode(status); ex.setReason(propFind.getStatusText()); throw ex; } } /** * * @param client * @param httpURL * @param lockToken the locktoken to be used or <code>null</code> if * none is to be used * @throws IOException * @throws HttpException */ public static boolean assureExistingCollection(HttpClient client, HttpURL httpURL, String lockToken) throws IOException, HttpException { String path = httpURL.getPath(); if (!path.endsWith("/")) { path = path + "/"; } Stack toBeCreated = new Stack(); while (!path.equals("/")) { HttpURL parent = Utils.createHttpURL(httpURL, path); if (!collectionExists(client, parent)) { toBeCreated.push(path); path = path.substring(0, path.lastIndexOf("/", path.length() - 2) + 1); } else { break; } } boolean created = !toBeCreated.empty(); while (!toBeCreated.empty()) { HttpURL newColl = Utils.createHttpURL(httpURL, (String) toBeCreated.pop()); MkcolMethod mkcol = new MkcolMethod(newColl.getEscapedURI()); mkcol.setFollowRedirects(true); generateIfHeader(mkcol, lockToken); int status = client.executeMethod(mkcol); if (status != WebdavStatus.SC_CREATED) { HttpException ex = new HttpException("Can't create collection " + newColl); ex.setReasonCode(status); ex.setReason(mkcol.getStatusText()); throw ex; } } return created; } public static void putFile(HttpClient client, HttpURL url, InputStream is, String contentType, String lockToken) throws IOException, HttpException { PutMethod put = new PutMethod(url.getEscapedURI()); generateIfHeader(put, lockToken); put.setRequestHeader("Content-Type", contentType); put.setRequestBody(is); put.setFollowRedirects(true); int status = client.executeMethod(put); switch (status) { case WebdavStatus.SC_OK: case WebdavStatus.SC_CREATED: case WebdavStatus.SC_NO_CONTENT: return; default: HttpException ex = new HttpException(); ex.setReason(put.getStatusText()); ex.setReasonCode(status); throw ex; } } public static InputStream getFile(HttpClient client, HttpURL url) throws IOException, HttpException { GetMethod get = new GetMethod(url.toString()); get.setFollowRedirects(true); int status = client.executeMethod(get); switch (status) { case WebdavStatus.SC_OK: return get.getResponseBodyAsStream(); default: HttpException ex = new HttpException(); ex.setReason(get.getStatusText()); ex.setReasonCode(status); throw ex; } } public static void generateIfHeader(HttpMethod method, String lockToken) { if (lockToken != null) { Header ifHeader = new Header(); ifHeader.setName("If"); ifHeader.setValue("(<" + lockToken + ">)"); method.addRequestHeader(ifHeader); } } public static String lockResource(HttpClient client, HttpURL url, String ownerInfo, int depth, int timeout) throws IOException, HttpException { LockMethod lock = new LockMethod(url.getEscapedURI()); lock.setDepth(depth); lock.setTimeout(timeout); lock.setOwner(ownerInfo); //lock.setDebug(1); lock.setFollowRedirects(true); int status = client.executeMethod(lock); if (status == WebdavStatus.SC_OK) { Header header = lock.getResponseHeader("Lock-Token"); if (header != null) { String l = header.getValue(); return l.substring(1, l.length() - 1); } else { String l = lock.getLockToken(); if (l != null) { return l; } throw new WebdavException("LOCK does not provide a lock token."); } } else if (status == WebdavStatus.SC_MULTI_STATUS) { throw Utils.makeBuildException("Can't lock", lock.getResponses()); } else { throw Utils.makeBuildException("Can't lock", status, lock.getStatusText()); } } public static void unlockResource(HttpClient client, HttpURL url, String lockToken) throws IOException, HttpException { UnlockMethod unlock = new UnlockMethod(url.getEscapedURI(), lockToken); unlock.setFollowRedirects(true); int status = client.executeMethod(unlock); switch (status) { case WebdavStatus.SC_OK: case WebdavStatus.SC_NO_CONTENT: return; default: HttpException ex = new HttpException(); ex.setReasonCode(status); ex.setReason(unlock.getStatusText()); throw ex; } } public static void copyResource(HttpClient client, HttpURL url, String destination, int depth, boolean overwrite) throws IOException, HttpException { CopyMethod copy = new CopyMethod(url.getEscapedURI(), destination, overwrite, depth); copy.setFollowRedirects(true); int status = client.executeMethod(copy); switch (status) { case WebdavStatus.SC_OK: case WebdavStatus.SC_CREATED: case WebdavStatus.SC_NO_CONTENT: return; default: HttpException ex = new HttpException(); ex.setReasonCode(status); ex.setReason(copy.getStatusText()); throw ex; } } public static void moveResource(HttpClient client, HttpURL url, String destination, boolean overwrite) throws IOException, HttpException { MoveMethod move = new MoveMethod(url.getEscapedURI(), destination, overwrite); move.setFollowRedirects(true); int status = client.executeMethod(move); switch (status) { case WebdavStatus.SC_OK: case WebdavStatus.SC_CREATED: case WebdavStatus.SC_NO_CONTENT: return; default: HttpException ex = new HttpException(); ex.setReasonCode(status); ex.setReason(move.getStatusText()); throw ex; } } public static BuildException makeBuildException(String msg, Exception e) { if (e instanceof HttpException) { HttpException he = (HttpException) e; return new BuildException(msg + " " + e.getMessage() + " (" + (he.getReason() != null ? he.getReason() : HttpStatus.getStatusText(he.getReasonCode())) + ")"); } else { return new BuildException(msg + " (" + e.toString() + ")", e); } } public static BuildException makeBuildException(String msg, int status) { return new BuildException(msg + " (" + HttpStatus.getStatusText(status) + ")"); } public static BuildException makeBuildException(String msg, int status, String statusText) { return new BuildException(msg + " (" + status + ", " + statusText + ")"); } public static BuildException makeBuildException(String msg, Enumeration enumOfResponseEntities) { StringBuffer b = new StringBuffer(); b.append(msg).append("\n"); for (; enumOfResponseEntities.hasMoreElements();) { ResponseEntity e = (ResponseEntity) enumOfResponseEntities.nextElement(); b.append(e.getHref()).append(" ").append(HttpStatus.getStatusText(e.getStatusCode())).append("\n"); } return new BuildException(b.toString()); } public static HttpURL createHttpURL(HttpURL base, String relative) throws URIException { if (base instanceof HttpsURL) { return new HttpsURL((HttpsURL) base, relative); } else { return new HttpURL(base, relative); } } public static HttpURL createHttpURL(String url) throws URIException { if (url.startsWith("https://")) { return new HttpsURL(url); } else { return new HttpURL(url); } } }