All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.webdav.client.AbstractResourceHandle Maven / Gradle / Ivy

Go to download

We build this plugin because eclipse no longer distributes it and Guvnor tools needs it.

There is a newer version: 7.48.0.Final
Show newest version
package org.eclipse.webdav.client;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import org.eclipse.webdav.*;
import org.eclipse.webdav.dom.*;
import org.eclipse.webdav.internal.kernel.*;
import org.eclipse.webdav.internal.kernel.utils.Assert;
import org.eclipse.webdav.internal.kernel.utils.EmptyEnumeration;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * The AbstractResourceHandle class is the abstract
 * superclass for all types of resource references.  A resource
 * handle is a client-side 'proxy' for the server resource.  Instances
 * of handle classes understand the methods appropriate for the
 * corresponding server resource and provide a convenient high-level
 * API for sending WebDAV methods to the server to manipulate
 * the resource.
 * 

* It is certainly posible to create a stale or invalid handle in * numerous ways. For example, the existance of a handle does not * imply the existance of a corresponding server resource (indeed * resource can be created by sending create() to a handle, or deleted * using delete() -- so the life cycles are not coupled. It is also * possible to create, say, a collection handle on a regular resource * and invoke invalid WebDAV methods. These will typically result * in an exception.

*

* The API on these classes are intended to convenience methods for * the most common operations on server resources. They make some * assumptions about the way you want to receive the results. To * get finer (but possibly less convenient) control over the WebDAV * methods use the Server interface of DAVClient * directly.

*/ public abstract class AbstractResourceHandle implements WebDAVPropertyNames, WebDAVPropertyValues { // The DAVClient that is used to access the WebDAV server. // Given during initialization, this object contains the // authentication and proxy information etc. protected DAVClient davClient; // The Locator represents the universal identifier of the server // resource. protected ILocator locator; /** * Creates a new AbstractResourceHandle with the given * DAV client and Locator. * * @param davClient the DAVClient that contains the server * reference and proxy/authentication information. * @param locator the Locator identity of the resource. */ public AbstractResourceHandle(DAVClient davClient, ILocator locator) { Assert.isNotNull(davClient); Assert.isNotNull(locator); this.davClient = davClient; this.locator = locator; } /** * Answer a new collection handle on the same underlying server resource. * Since the handle represents a means of accessing the resource, it is valid to * consider a collection resource as a collection or regular resource depending * upon how it is being accessed. Note that not all resources have collection * semantics. * * @return an equivalent collection handle on the resource. */ public CollectionHandle asCollectionHandle() { return new CollectionHandle(davClient, locator); } /** * Answer a new resource handle on the same underlying server resource. * Since the handle represents a means of accessing the resource, it is valid to * consider a collection resource as a collection or regular resource depending * upon how it is being accessed. * * @return an equivalent handle on the resource. */ public ResourceHandle asResourceHandle() { return new ResourceHandle(davClient, locator); } /** * Return a boolean value indicating whether or not the server for this resource * is DAV compliant. * * @return boolean true if the server can respond to DAV * requests, or false otherwise. * @exception DAVException if there was a problem checking for DAV compliance */ public boolean canTalkDAV() throws DAVException { IResponse response = null; try { // Send an options request. response = davClient.options(locator, newContext()); examineResponse(response); // Check for at least DAV level 1. String davHeader = response.getContext().getDAV(); return !((davHeader == null) || (davHeader.indexOf("1") == -1)); //$NON-NLS-1$ } catch (IOException exception) { throw new SystemException(exception); } finally { closeResponse(response); } } /** * Check-in this resource. Returns a handle on the new version. *

* Note that versioned collections do not have internal members * so they are represented by ResourceHandle handles.

*

* If the receiver is a working resource it becomes invalid after * the check in (because the server deletes the working resource), * however, if the receiver is a version-controlled resource the * receiver can be used as a checked-in resource.

* * @return a handle to the newly created version. * @throws DAVException if a problem occurs with the check in on * the WebDAV server. */ public ResourceHandle checkIn() throws DAVException { ILocator versionLocator = protectedCheckIn(); return new ResourceHandle(davClient, versionLocator); } /** * Check out this resource. Returns a resource handle on the checked out * version-controlled resource, or the working resource if a version is checked * out. *

* Note that a checked-out version-controlled collection has members that are * themselves version-controlled resources, or unversioned resources; however, * working collection members are always version history resources.

* * @throws DAVException if a problem occurs checking out the resource. */ public abstract AbstractResourceHandle checkOut() throws DAVException; /** * Helper method to close a response from the server. *

* Note that the argument MAY be null in which case * the call has no effect.

* * @param response the response from the server, or null
* denoting a no-op. * @throws SystemException if a problem occurred closing the response. */ protected void closeResponse(IResponse response) throws SystemException { if (response == null) return; try { response.close(); } catch (IOException e) { throw new SystemException(e); } } /** * Make a copy of this resource and place it at the location defined * by the given locator. *

* Uses default values of depth: infinity and overwrite: false for * the copy.

* * @param destination the Locator to the destination of the copy. * @exception DAVException if there was a problem copying this resource. * @see IServer#copy(ILocator, ILocator, IContext, Document) */ public void copy(ILocator destination) throws DAVException { copy(destination, IContext.DEPTH_INFINITY, false, null); } /** * Make a copy of this resource and place it at the location specified * by the given destination locator. * * @param destination the location to put the copy. * @param depth how deep to make the copy. * @param overwrite how to react if a resource already exists at the destination. * @param propertyNames Collection of QualifiedNames * of properties that MUST be copied as live properties. Specifying null * mean that all properties must be kept alive; specifying an empty collection allows for * no properties to be kept live. (ref http://andrew2.andrew.cmu.edu/rfc/rfc2518.html#sec-12.12.1) * @exception DAVException if there was a problem copying this resource. * @see IServer#copy(ILocator, ILocator, IContext, Document) */ public void copy(ILocator destination, String depth, boolean overwrite, Collection propertyNames) throws DAVException { // Define the request context. IContext context = newContext(); context.setDepth(depth); context.setOverwrite(overwrite); // Set up the request body to specify which properties should be kept alive. Document document = newDocument(); PropertyBehavior propertyBehavior = PropertyBehavior.create(document); if (propertyNames == null) propertyBehavior.setIsKeepAllAlive(true); else { Iterator namesItr = propertyNames.iterator(); while (namesItr.hasNext()) { QualifiedName name = (QualifiedName) namesItr.next(); String nameURI = name.getQualifier() + "/" + name.getLocalName(); //$NON-NLS-1$ propertyBehavior.addProperty(nameURI); } // end-while } // end-if // Call the server to perform the copy. IResponse response = null; try { response = davClient.copy(locator, destination, context, document); examineResponse(response); examineMultiStatusResponse(response); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Create this resource in the repository. *

* Subclasses should override this method with the correct behavior * for their type.

* * @exception DAVException if there was a problem creating * this resource. */ public abstract void create() throws DAVException; /** * Delete this resource from the repository. *

* As a convenience, if the resource does not exist this method will * do nothing (rather than throw an exception). If the caller needs to know * if a resource was deleted they can use delete(boolean). * * @exception DAVException if there was a problem deleting this resource. * @see #delete(boolean) * @see IServer#delete(Locator, Context) */ public void delete() throws DAVException { // As a convenience, we will assume an attempt to // delete a missing resource is a successful outcome. delete(false); } /** * Answers true iff the receiver and the argument are considered equal, * otherwise answers false. *

* Note that this is a handle equivalence test, and does not imply * that the resources are the same resource on the server. Indeed, * the method does not contact the server.

* * @param obj the target of the comparison. * @return whether the two objects are equal. */ public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof AbstractResourceHandle)) return false; AbstractResourceHandle otherHandle = (AbstractResourceHandle) obj; // It all comes down to locator equality. return locator.equals(otherHandle.locator); } /** * Answers the hashcode of the receiver as defined by Object#hashCode(). * * @return the receiver's hash code. */ public int hashCode() { return locator.hashCode(); } /** * If the given response contains a multistatus body, the bodies status' * are checked for errors. If an error is found, an exception is thrown. * * @param response the response from the server to examine. * @throws DAVException if the given response contains a multistatus * body that contains a status code signalling an error. */ protected void examineMultiStatusResponse(IResponse response) throws DAVException { // If it is not a multistatus we don't look at it. if (response.getStatusCode() != IResponse.SC_MULTI_STATUS) return; // It is declared a multistatus, so if there is no response body // then that is a problem. if (!response.hasDocumentBody()) throw new DAVException(Policy.bind("exception.responseMustHaveDocBody")); //$NON-NLS-1$ // Extract the XML document from the response. Element documentElement; try { documentElement = response.getDocumentBody().getDocumentElement(); if (documentElement == null) throw new DAVException(Policy.bind("exception.invalidDoc")); //$NON-NLS-1$ } catch (IOException exception) { throw new SystemException(exception); } // Enumerate all the responses in the multistat and check that // they are indicating success (i.e. are 200-series response codes). try { MultiStatus multistatus = new MultiStatus(documentElement); Enumeration responseEnum = multistatus.getResponses(); while (responseEnum.hasMoreElements()) { ResponseBody responseBody = (ResponseBody) responseEnum.nextElement(); Enumeration propstatEnum = responseBody.getPropStats(); while (propstatEnum.hasMoreElements()) { PropStat propstat = (PropStat) propstatEnum.nextElement(); examineStatusCode(propstat.getStatusCode(), propstat.getResponseDescription()); } // end-while } // end-while } catch (MalformedElementException e) { throw new SystemException(e); } } /** * Check the status code of the given response and throw a WebDAV * exception if the code indicates failure. * * @param response the response to check * @exception WebDAVException if the server returned an HTTP/WebDAV * error code (i.e., anything outside the 200-series codes). */ protected void examineResponse(IResponse response) throws WebDAVException { examineStatusCode(response.getStatusCode(), response.getStatusMessage()); } /** * Helper method to extract the property status response from * a multi status reponse, and populate a URLTable with the * results. * * @param multiStatus an editor on the response from the server. * @return all the property status in a URLTable. * @throws IOException if there is a problem parsing the resource URLs. * @throws MalformedElementException if the XML is badly formed. */ protected URLTable extractPropStats(MultiStatus multiStatus) throws IOException, MalformedElementException { // Construct a URLTable to return to the user. URLTable reply = new URLTable(); // For each response (resource). Enumeration responses = multiStatus.getResponses(); while (responses.hasMoreElements()) { ResponseBody responseBody = (ResponseBody) responses.nextElement(); String href = responseBody.getHref(); // The href may be relative to the request URL. URL resourceURL = new URL(new URL(locator.getResourceURL()), href); Hashtable properties = new Hashtable(); reply.put(resourceURL, properties); // For each property status grouping. Enumeration propstats = responseBody.getPropStats(); while (propstats.hasMoreElements()) { PropStat propstat = (PropStat) propstats.nextElement(); org.eclipse.webdav.dom.Status status = new org.eclipse.webdav.dom.Status(propstat.getStatus()); // For each property with this status. Enumeration elements = propstat.getProp().getProperties(); while (elements.hasMoreElements()) { Element element = (Element) elements.nextElement(); QualifiedName name = ElementEditor.getQualifiedName(element); // Add a property status object to the result set. PropertyStatus propertyStatus = new PropertyStatus(element, status.getStatusCode(), status.getStatusMessage()); properties.put(name, propertyStatus); } // end-while } // end-while } // end-while return reply; } /** * Return the content of this resource as an input stream. The input * stream should be closed by the user. * * @return the input stream * @exception DAVException if there was a problem getting the contents * @see IServer#get(Locator, Context) */ public ResponseInputStream getContent() throws DAVException { IResponse response = null; try { response = davClient.get(locator, newContext()); examineResponse(response); } catch (IOException e) { closeResponse(response); throw new SystemException(e); } return new ResponseInputStream(response); } /** * Answer the DAVClient being used by this resource handle for accessing * the resource. * * @return the receiver's DAVClient. */ public DAVClient getDAVClient() { return davClient; } /** * Return the locator for this resource. * * @return the locator for this resource */ public ILocator getLocator() { return locator; } /** * Return an Enumeration over ActiveLocks which lists the locks currently * held on this resource. Return an empty enumeration if the lock discovery * property is not found on the resource. * * @return the enumeration of active locks * @exception DAVException if there was a problem getting the locks * @see #getProperty(QualifiedName) */ public Enumeration getLocks() throws DAVException { LockDiscovery lockdiscovery = null; try { Element element = getProperty(DAV_LOCK_DISCOVERY).getProperty(); lockdiscovery = new LockDiscovery(element); return lockdiscovery.getActiveLocks(); } catch (WebDAVException exception) { if (exception.getStatusCode() == IResponse.SC_NOT_FOUND) return new EmptyEnumeration(); throw exception; } catch (MalformedElementException elemException) { throw new SystemException(elemException); } } /** * Returns a collection handle for the parent of this resource. *

* Note that this method does NOT perform a method call to the * server to ensure that the collection exists.

*

* Returns null if this resource is the root. * * NOTE * The parent of a resource is, in general, ambiguous and may not * be immediately discernable from a resource locator. For example, * a locator with a 'label' qualifier will identify a version of a version- * controlled resource, and the parent will not be found by a simple URL * operation. Where a handle is created on a stable URL (i.e. a version URL) * there is no concept of a 'parent' resource. * Clients require further contextual information to determine * the 'parent' of a resource in these cases. * * @return the handle for the parent of this resource, or * null. */ public CollectionHandle getParent() throws DAVException { Assert.isTrue(locator.getLabel() == null); Assert.isTrue(!locator.isStable()); try { URL url = URLTool.getParent(locator.getResourceURL()); if (url == null) return null; String parentName = url.toString(); ILocator parentLocator = davClient.getDAVFactory().newLocator(parentName); return new CollectionHandle(davClient, parentLocator); } catch (MalformedURLException e) { throw new SystemException(e); } } /** * Return a URLTable which contains all of this resources * properties to the given depth. The returned URLTable * maps resource URLs to Hashtables * which in turn maps property QualifiedNames to * PropertyStatus. * * @param depth the depth of the request; for example, * Context.DEPTH_ZERO. * @return a URLTable containing properties. * @exception DAVException if there was a problem retrieving the properties. * @see #getProperties(Collection, String) */ public URLTable getProperties(String depth) throws DAVException { return getProperties((Collection) null, depth); } /** * Fetches and returns the specified properties for this resource and its * children to the given depth. The returned table is a URLTable of * hashtables. The keys in the first table are the URLs of * the resources. The nested table is a table where the keys are the names * (QualifiedName) of the properties and the values are the * properties' values (PropertyStatus). * * @param propertyNames collection of property names to search for * (QualifiedName), or null to retrieve * all properties. * @param depth the depth of the search (eg. Context.DEPTH_INFINITY) * @return URLTable of hashtables keyed by resource URLKey * then by property name. * @exception DAVException if there was a problem fetching the properties. * @see IServer#propfind(Locator, Context, Document) */ public URLTable getProperties(Collection propertyNames, String depth) throws DAVException { // Set up the request context. IContext context = newContext(); context.setDepth(depth); // Set up the request body. Document document = newDocument(); PropFind propfind = PropFind.create(document); // null is a special value meaning 'all properties'. if (propertyNames == null) propfind.setIsAllProp(true); else { // Add all the property names to the request body. Prop prop = propfind.setProp(); Iterator namesItr = propertyNames.iterator(); while (namesItr.hasNext()) prop.addPropertyName((QualifiedName) namesItr.next()); } // Were ready to make the server call. IResponse response = null; try { // This contacts the server. response = davClient.propfind(locator, context, document); examineResponse(response); // Create a multi-status element editor on the response. if (!response.hasDocumentBody()) throw new DAVException(Policy.bind("exception.respMustShareXMLDoc")); //$NON-NLS-1$ Element documentElement = response.getDocumentBody().getDocumentElement(); if (documentElement == null) throw new DAVException(Policy.bind("exception.respHasInvalidDoc")); //$NON-NLS-1$ MultiStatus multiStatus = new MultiStatus(documentElement); // Construct a URLTable of results to return to the user. return extractPropStats(multiStatus); } catch (IOException e) { throw new SystemException(e); } catch (MalformedElementException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Return the property status for the property with the given name. * * @param propertyName the name of the property * @return the property status * @exception DAVException if there was a problem getting the property * @see #getProperties(Collection, String) */ public PropertyStatus getProperty(QualifiedName propertyName) throws DAVException { Collection names = new HashSet(); names.add(propertyName); URLTable result = getProperties(names, IContext.DEPTH_ZERO); URL url = null; try { url = new URL(locator.getResourceURL()); } catch (MalformedURLException e) { throw new SystemException(e); } Hashtable propTable = (Hashtable) result.get(url); if (propTable == null) throw new DAVException(Policy.bind("exception.lookup", url.toExternalForm())); //$NON-NLS-1$ return (PropertyStatus) propTable.get(propertyName); } /** * Fetch and return the property names for the resource, and the children * resources to the specified depth. Returns URLTable * mapping resource URLs to enumerations over the property names for that * resource. * * @param depth eg. Context.DEPTH_ZERO * @return a URLTable of Enumerations over * QualfiedNames * @throws DAVException if there was a problem getting the property names * @see IServer#propfind(Locator, Context, Document) */ public URLTable getPropertyNames(String depth) throws DAVException { // create and send the request IContext context = newContext(); context.setDepth(depth); IResponse response = null; try { Document document = newDocument(); PropFind propfind = PropFind.create(document); propfind.setIsPropName(true); response = davClient.propfind(locator, context, document); examineResponse(response); if (!response.hasDocumentBody()) { throw new DAVException(Policy.bind("exception.respMustHaveElmtBody")); //$NON-NLS-1$ } Element documentElement = response.getDocumentBody().getDocumentElement(); if (documentElement == null) { throw new DAVException(Policy.bind("exception.bodyMustHaveElmt")); //$NON-NLS-1$ } MultiStatus multistatus = new MultiStatus(documentElement); //construct the URLTable to return to the user URLTable reply = new URLTable(10); Enumeration responses = multistatus.getResponses(); while (responses.hasMoreElements()) { ResponseBody responseBody = (ResponseBody) responses.nextElement(); String href = responseBody.getHref(); URL resourceUrl = new URL(new URL(locator.getResourceURL()), href); Enumeration propstats = responseBody.getPropStats(); Vector vector = new Vector(); while (propstats.hasMoreElements()) { PropStat propstat = (PropStat) propstats.nextElement(); Prop prop = propstat.getProp(); Enumeration names = prop.getPropertyNames(); while (names.hasMoreElements()) { QualifiedName dname = (QualifiedName) names.nextElement(); vector.addElement(dname); } } reply.put(resourceUrl, vector.elements()); } return reply; } catch (IOException e) { throw new SystemException(e); } catch (MalformedElementException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Retrieve the version tree infomration for the receiver, assuming * that the receiver is a version or a version-controlled resource. *

* The version tree info comprises a URLTable whose keys * are the URLs of each version in the version history, * and whose values are Vectors of the resource's immediate * predecessor URLs. Note that the root version is * (uniquely) identified by an empty set of predecessors.

* * @return the map from resource URL to predecessor set. */ public URLTable getVersionTree() throws DAVException { // Issue a version tree report against the receiver to retrieve // the successor set of all the versions. Document document = newDocument(); Element root = ElementEditor.create(document, "version-tree"); //$NON-NLS-1$ Element propElement = ElementEditor.appendChild(root, "prop"); //$NON-NLS-1$ ElementEditor.appendChild(propElement, "predecessor-set"); //$NON-NLS-1$ IResponse response = null; try { // Run the REPORT and check for errors. response = davClient.report(locator, newContext(), document); examineResponse(response); if (!response.hasDocumentBody()) throw new DAVException(Policy.bind("exception.respMustHaveElmtBody")); //$NON-NLS-1$ // Get the body as a MultiStatus. Element documentElement = response.getDocumentBody().getDocumentElement(); if (documentElement == null) throw new DAVException(Policy.bind("exception.bodyMustHaveElmt")); //$NON-NLS-1$ MultiStatus multistatus = new MultiStatus(documentElement); // Construct the predecessor table. // This will contain the result. URLTable predecessorTable = new URLTable(); // For each response. Enumeration responses = multistatus.getResponses(); while (responses.hasMoreElements()) { ResponseBody responseBody = (ResponseBody) responses.nextElement(); // Get the absolute URL of the resource. String href = responseBody.getHref(); URL resourceURL = new URL(new URL(locator.getResourceURL()), href); // Add an entry to the predecessor table. Vector predecessors = new Vector(); predecessorTable.put(resourceURL, predecessors); // For each propstat. Enumeration propstats = responseBody.getPropStats(); while (propstats.hasMoreElements()) { PropStat propstat = (PropStat) propstats.nextElement(); // We are going to assume that the status is OK, or error out. if (propstat.getStatusCode() != IResponse.SC_OK) throw new DAVException(Policy.bind("exception.errorRetrievingProp")); //$NON-NLS-1$ // For each property in the prop (there should only be one). Prop prop = propstat.getProp(); Enumeration elements = prop.getProperties(); while (elements.hasMoreElements()) { Element element = (Element) elements.nextElement(); // Look explicitly for the DAV:predecessor-set QualifiedName name = ElementEditor.getQualifiedName(element); if (name.equals(DAV_PREDECESSOR_SET)) { Enumeration e = new HrefSet(element, DAV_PREDECESSOR_SET).getHrefs(); while (e .hasMoreElements()) { URL predURL = new URL((String) e.nextElement()); predecessors.add(predURL); } // end-while } //end-if } // end-while } // end-while } //end-while // Phew, were done. return predecessorTable; } catch (IOException e) { throw new SystemException(e); } catch (MalformedElementException e) { throw new SystemException(e); } finally { closeResponse(response); } } public CollectionHandle[] getWorkspaceCollections() throws DAVException { PropertyStatus propertyStatus = getProperty(DAV_WORKSPACE_COLLECTION_SET); Vector v = new Vector(5); Element element = propertyStatus.getProperty(); if (!ElementEditor.isDAVElement(element, "workspace-collection-set")) //$NON-NLS-1$ throw new DAVException(Policy.bind("exception.malformedElement")); //$NON-NLS-1$ Element child = ElementEditor.getFirstChild(element, "href"); //$NON-NLS-1$ while (child != null) { String href = ElementEditor.getFirstText(child); ILocator locator = davClient.getDAVFactory().newLocator(href); v.addElement(new CollectionHandle(davClient, locator)); child = ElementEditor.getNextSibling(child); } CollectionHandle[] result = new CollectionHandle[v.size()]; v.copyInto(result); return result; } /** * Return the header from a message send to the server. * * @return a context with the message header contents * @exception DAVException if there was a problem sending the message * @see IServer#head(Locator, Context) */ public IContext head() throws DAVException { IResponse response = null; try { response = davClient.head(locator, newContext()); examineResponse(response); return response.getContext(); } catch (IOException exception) { throw new SystemException(exception); } finally { closeResponse(response); } } /** * Return a boolean value indicating whether or not this resource is a * collection. *

* A resource is a collection (i.e., implements collection semantics) if * it's resource type includes a <DAV:collection> element.

* * @return boolean true if the resource implements collection * semantics, and false otherwise. */ public boolean isCollection() throws DAVException { return propertyHasChild(DAV_RESOURCE_TYPE, DAV_COLLECTION_RESOURCE_TYPE); } /** * Return a boolean value indicating whether or not this resource * is currently locked. * * @return boolean indicator * @exception DAVException if there was a problem getting the locks * @see #getLocks() */ public boolean isLocked() throws DAVException { // see if there are any active locks return getLocks().hasMoreElements(); } /** * Lock this resource with default values. * *

Note: default values of DEPTH_ZERO for depth and -1 for timeout are used.

* * @return the lock token * @exception DAVException if there was a problem locking this resource * @see #lock(boolean, String, int, String) */ public LockToken lock() throws DAVException { return lock(false, IContext.DEPTH_ZERO, -1, null); } /** * Lock this resource using the specified parameters. * * @param isShared true if the lock is shared, false if the lock is exclusive * @param depth eg. Context.DEPTH_ZERO * @param timeout the timeout value for the lock * @param owner the owner of the lock * @return the lock token * @exception DAVException if there was a problem locking this resource * @see IServer#lock(Locator, Context, Document) */ public LockToken lock(boolean isShared, String depth, int timeout, String owner) throws DAVException { // Define the request context. IContext context = newContext(); context.setDepth(depth); context.setTimeout(timeout); // Create the request body. Document document = newDocument(); LockInfo lockinfo = LockInfo.create(document); lockinfo.setIsShared(isShared); // Add the owner if it is given. if (owner != null) { Owner ownerEditor = lockinfo.setOwner(); ownerEditor.getElement().appendChild(document.createTextNode(owner)); } // Send the lock request. IResponse response = null; try { response = davClient.lock(locator, context, document); examineResponse(response); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } // Extract the token from the resulting context. LockToken token = new LockToken(response.getContext().getLockToken()); //fServerManager.addLock(newURL(fLocator.getResourceURL()), token, depth); return token; } /** * Move this resource to the destination specified by the given locator. * Use default values for overwrite and properties to move. * * @param destination the location to move this resource to * @exception DAVException if there was a problem moving this resource * @see #move(Locator, boolean, Enumeration) */ public void move(ILocator destination) throws DAVException { move(destination, false, null); } /** * Move this resource to the location specified by the given locator. * If a resource already exists at the destination and the overwrite * boolean is true, then write over top of the existing resource. Otherwise * do not. The enumeration is over qualified names which are the names of * the properties to move. * * @param destination the location to move to * @param overwrite how to react if a resource already exists at the * destination * @param names Enumeration over QualifiedNames * @exception DAVException if there was a problem moving this resource * @see IServer#move(Locator, Locator, Context, Document) */ public void move(ILocator destination, boolean overwrite, Enumeration names) throws DAVException { IContext context = newContext(); context.setOverwrite(overwrite); Document document = newDocument(); PropertyBehavior propertyBehavior = PropertyBehavior.create(document); if (names == null) { propertyBehavior.setIsKeepAllAlive(true); } else { while (names.hasMoreElements()) { Object obj = names.nextElement(); Assert.isTrue(obj instanceof QualifiedName, Policy.bind("assert.propNameMustBeEnumOverQual")); //$NON-NLS-1$ // fix this...can we really add property names to href elements? propertyBehavior.addProperty(((QualifiedName) obj).getLocalName()); } } IResponse response = null; try { response = davClient.move(locator, destination, context, document); examineResponse(response); examineMultiStatusResponse(response); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Answer a new empty context for requests sent to the * receivers server. * * @return a new request Context. */ protected IContext newContext() { return davClient.getDAVFactory().newContext(); } /** * Answer a new empty DOM Document suitable for creating requests * to the receiver's server. * * @return a new DOM Document. */ protected Document newDocument() { return davClient.getDAVFactory().newDocument(); } /** * Check in the receiver and answer a new Locator on the * resulting version resource. * * @return the Locator to the receiver's version. * @throws DAVException if a problem occurs with the check in request. */ protected ILocator protectedCheckIn() throws DAVException { IResponse response = null; try { response = davClient.checkin(locator, newContext(), null); examineResponse(response); String versionUrl = response.getContext().getLocation(); return davClient.getDAVFactory().newStableLocator(versionUrl); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Check out the receiver and answer a new Locator on the * resulting checked out resource. The result MAY be the same * as the receiver's Locator if the server did not create * a new resource as a consequence of the check out (i.e. * if it was checking out a vesion-controlled resource rather * than a version). * * @return the Locator to the receiver's version. * @throws DAVException if a problem occurs with the check in request. */ protected ILocator protectedCheckOut() throws DAVException { IResponse response = null; try { response = davClient.checkout(locator, newContext(), null); examineResponse(response); String resourceUrl = response.getContext().getLocation(); return davClient.getDAVFactory().newStableLocator(resourceUrl); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Refresh the lock on this resource with the given lock token. Use * the specified timeout value. * * @param lockToken the lock token to refresh * @param timeout the new timeout value to use * @exception DAVException if there was a problem refreshing the lock */ public void refreshLock(LockToken lockToken, int timeout) throws DAVException { // Set up the request in the context. IContext context = newContext(); context.setTimeout(timeout); context.setLockToken(lockToken.getToken()); // Send the request to the server. IResponse response = null; try { response = davClient.lock(locator, context, null); examineResponse(response); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Remove the properties with the given names, from this resource. * * @param propertyNames Enumeration over * QualifiedNames * @exception DAVException if there was a problem removing the * properties * @see IServer#proppatch(Locator, Context, Document) */ public void removeProperties(Collection propertyNames) throws DAVException { Assert.isNotNull(propertyNames); // Removing no properties is easy. if (propertyNames.isEmpty()) return; // Add the names of the properties to remove to the request body. Document document = newDocument(); PropertyUpdate propertyUpdate = PropertyUpdate.create(document); Prop prop = propertyUpdate.addRemove(); Iterator namesItr = propertyNames.iterator(); while (namesItr.hasNext()) prop.addPropertyName((QualifiedName) namesItr.next()); // Send the PROPPATCH request. IResponse response = null; try { response = davClient.proppatch(locator, newContext(), document); examineResponse(response); examineMultiStatusResponse(response); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Remove the property with the given name from this resource. * * @param propertyName the name of the property to remove * @exception DAVException if there was a problem removing the property * @see #removeProperties(Collection) */ public void removeProperty(QualifiedName propertyName) throws DAVException { Collection propertyNames = new Vector(1); propertyNames.add(propertyName); removeProperties(propertyNames); } /** * Set the content of this resource to be the untyped data stored in the given * input stream. * The stream will automatically be closed after the data * is consumed. If the resource does not exist it is created with the * given content. * * @param input the inputstream containing the resource contents. * @exception DAVException if there was a problem setting the contents. * @see #setContent(String, InputStream) * @see IServer#put(Locator, Context, InputStream) */ public void setContent(InputStream input) throws DAVException { setContent("application/octet-stream", input); //$NON-NLS-1$ } /** * Set the content of this resource to be the data stored in the given * input stream. The type encoding is given in the content type argument, and * should be in the media format described by RFC2616 Sec 3.7. * The stream will automatically be closed after the data * is consumed. If the resource does not exist it is created with the * given content. * * @param contentType the media type for the data on the input stream. * @param input the inputstream containing the resource contents. * @exception DAVException if there was a problem setting the contents. * @see IServer#put(Locator, Context, InputStream) */ public void setContent(String contentType, InputStream input) throws DAVException { IResponse response = null; try { IContext context = newContext(); context.setContentType(contentType); response = davClient.put(locator, context, input); examineResponse(response); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Set the given properties on this resource. * * @param properties a Collection of property Elements. * @exception DAVException if there was a problem setting the properties. * @see IServer#proppatch(Locator, Context, Document) */ public void setProperties(Collection properties) throws DAVException { Assert.isNotNull(properties); // Setting no properties is a no-op. if (properties.isEmpty()) return; // Build the request body to describe the properties to set. Document document = newDocument(); PropertyUpdate propertyUpdate = PropertyUpdate.create(document); Prop prop = propertyUpdate.addSet(); Iterator propertiesItr = properties.iterator(); while (propertiesItr.hasNext()) { Element element = (Element) propertiesItr.next(); try { prop.addProperty(element); } catch (MalformedElementException exception) { throw new SystemException(exception); } } // end-while // Send the request to the server and examine the response for failures. IResponse response = null; try { response = davClient.proppatch(locator, newContext(), document); examineResponse(response); examineMultiStatusResponse(response); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Set the given property on this resource. * * @param property the property to set * @exception DAVException if there was a problem setting the property * @see #setProperties(Collection) */ public void setProperty(Element property) throws DAVException { Collection properties = new Vector(1); properties.add(property); setProperties(properties); } /** * Return a string representation of this resource. Used for * debugging purposes only. * * @return this resource, as a string */ public String toString() { return locator.getResourceURL(); } /** * Send a message to the server. The contents of the resulting * input stream should be the message that was sent, echoed * back to the client. *

* The input stream should be closed by the user.

* * @return an input stream on the request as received. * @exception DAVException if there was a problem sending the * request to the server. * @see IServer#trace(Locator, Context) */ public ResponseInputStream trace() throws DAVException { IResponse response = null; try { response = davClient.trace(locator, newContext()); examineResponse(response); } catch (IOException e) { throw new SystemException(e); } catch (DAVException e) { closeResponse(response); throw e; } return new ResponseInputStream(response); } /** * Unlock this resource with the given lock token. * * @param token the lock token to remove from this resource * @exception DAVException if there was a problem unlocking this resource * @see IServer#unlock(Locator, Context) */ public void unlock(LockToken token) throws DAVException { // Send the lock token in the header of the request. IContext context = newContext(); context.setLockToken("<" + token.getToken() + ">"); //$NON-NLS-1$ //$NON-NLS-2$ IResponse response = null; try { response = davClient.unlock(locator, context); examineResponse(response); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Perform an UPDATE on the receiver to set the version it * is based upon. * * @param version the Locator of the version that * is the target of the update request. * @throws DAVException if a problem occurs executing the update * on the WebDAV server. */ public void update(ILocator version) throws DAVException { Document document = newDocument(); Update.createVersion(document, version.getResourceURL()); IResponse response = null; try { response = davClient.update(locator, newContext(), document); examineResponse(response); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Bring the receiver under version control. This means that * the receiver is replaced by a version-controlled resource. * Note that the client may send version control to a resource * that is already under version control with no adverse effects. * * @throws DAVException if a problem occurs bringing the * resource under version control. */ public void versionControl() throws DAVException { IResponse response = null; try { response = davClient.versionControl(locator, newContext(), null); examineResponse(response); } catch (IOException e) { throw new SystemException(e); } finally { closeResponse(response); } } /** * Delete this resource from the repository, optionally succeeding * in the delete if the resource was not found on the server. * * @param mustExist if true then the delete will * fail if the resource was not on the server at the time of the * delete request. If false the delete will succeed if * there was no such resource to delete. * @exception DAVException if there was a problem deleting * this resource. * @see IServer#delete(Locator, Context) */ public void delete(boolean mustExist) throws DAVException { IResponse response = null; try { response = davClient.delete(locator, newContext()); if (!mustExist && (response.getStatusCode() == IResponse.SC_NOT_FOUND)) return; examineResponse(response); examineMultiStatusResponse(response); } catch (IOException exception) { throw new SystemException(exception); } finally { closeResponse(response); } } /** * Check the given status code and throw a WebDAV * exception if the code indicates failure. If the code * is success, this method does nothing. * * @param code the status code to check. * @param message the status message accompanying the code. * @exception WebDAVException if the server returned an HTTP/WebDAV * error code (i.e., anything outside the 200-series codes). */ protected void examineStatusCode(int code, String message) throws WebDAVException { if (code >= 300 && code <= 399) throw new RedirectionException(code, message); if (code >= 400 && code <= 499) throw new ClientException(code, message); if (code >= 500 && code <= 599) throw new ServerException(code, message); } /** * Return a boolean value indicating whether or not this resource * exists on the server. *

* This implementation uses the HTTP HEAD method so the URL may or * may not exist in the DAV namespace. The DAV RESOURCE_TYPE property * is NOT checked.

* * @return boolean true if the resource exists on the server * or false otherwise. * @exception DAVException if there was a problem checking for * existence. */ public boolean exists() throws DAVException { // Test existance by issuing a HEAD request. IResponse response = null; try { response = davClient.head(locator, newContext()); // If the resource was not found, then that answers the question. if (response.getStatusCode() == IResponse.SC_NOT_FOUND) return false; // Otherwise check for errors. examineResponse(response); // No problems by this point, so the resource is there and OK. return true; } catch (IOException exception) { throw new SystemException(exception); } finally { closeResponse(response); } } /** * Check to see if the resource is checked in (i.e., is an immutable * resource). *

* The resource is checked in if it has a <DAV:checked-in> * property.

* * @return true if the resource is checked in * and false otherwise. * @throws DAVException if a problem occurs determining the state * of the resource. */ public boolean isCheckedIn() throws DAVException { return supportsLiveProperty(DAV_CHECKED_IN); } /** * Check to see if the resource is checked-out. *

* The resource is checked out if it has a <DAV:checked-out> * property.

* * @return true if the resource is checked out * and false otherwise. * @throws DAVException if a problem occurs determining the state * of the resource. */ public boolean isCheckedOut() throws DAVException { return supportsLiveProperty(DAV_CHECKED_OUT); } /** * Check to see if the resource is a version. *

* The resource is a version if it has <DAV:version-name> * in the <DAV:supported-live-properties-set>.

* * @return true if the resource is a version * and false otherwise. * @throws DAVException if a problem occurs determining the state * of the resource. */ public boolean isVersion() throws DAVException { return supportsLiveProperty(DAV_VERSION_NAME); } /** * Check to see if the resource is under version control. *

* The resource is version controlled if it has <DAV:auto-checkout> * in the <DAV:supported-live-properties-set>.

* * @return true if the resource is under version * control and false otherwise. * @throws DAVException if a problem occurs determining the state * of the resource. */ public boolean isVersionControlled() throws DAVException { return supportsLiveProperty(DAV_AUTO_CHECKOUT); } /** * Check to see if the resource is a working resource. *

* The resource is a working resource if it has * <DAV:checked-out> and does not have <DAV:auto-checkout> * in the <DAV:supported-live-properties-set>.

* * @return true if the resource is a working resource * and false otherwise. * @throws DAVException if a problem occurs determining the state * of the resource. */ public boolean isWorkingResource() throws DAVException { PropertyStatus propertyStat = getProperty(DAV_SUPPORTED_LIVE_PROPERTY_SET); // If the live-property-set is not supported, then the answer is 'no'. if (propertyStat.getStatusCode() == IResponse.SC_NOT_FOUND) return false; // If there was a problem getting the live property set, throw an exception. examineStatusCode(propertyStat.getStatusCode(), propertyStat.getStatusMessage()); // Check to see if the required properties are/are not in the supported set. try { Element propertySet = propertyStat.getProperty(); return ((ElementEditor.hasChild(propertySet, DAV_CHECKED_OUT)) && !(ElementEditor.hasChild(propertySet, DAV_AUTO_CHECKOUT))); } catch (MalformedElementException exception) { throw new SystemException(exception); } } /** * This is a helper method to check to see if the resource has a * property with the given name that in turn has a child with a * given name. * * @return true if the resource does have such a * property with a named child and false if it does * not have such a property or does not have such a child of the * property. * @throws DAVException if a problem occurs determining result * from the server. */ protected boolean propertyHasChild(QualifiedName propertyName, QualifiedName childName) throws DAVException { // If the property is not found, then the answer is 'no'. PropertyStatus propertyStat = getProperty(propertyName); if (propertyStat.getStatusCode() == IResponse.SC_NOT_FOUND) return false; // If there was a problem getting the property, throw an exception. examineStatusCode(propertyStat.getStatusCode(), propertyStat.getStatusMessage()); // Check to see if the named child is in the retrieved property. try { return ElementEditor.hasChild(propertyStat.getProperty(), childName); } catch (MalformedElementException exception) { throw new SystemException(exception); } } /** * Check to see if the resource supports the named live property. * * @return true if the resource does support the live * property and false otherwise. * @throws DAVException if a problem occurs determining result * from the server. */ public boolean supportsLiveProperty(QualifiedName propertyName) throws DAVException { return propertyHasChild(DAV_SUPPORTED_LIVE_PROPERTY_SET, propertyName); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy