001: package com.ibm.webdav;
002:
003: /*
004: * (C) Copyright IBM Corp. 2000 All rights reserved.
005: *
006: * The program is provided "AS IS" without any warranty express or
007: * implied, including the warranty of non-infringement and the implied
008: * warranties of merchantibility and fitness for a particular purpose.
009: * IBM will not be liable for any damages suffered by you as a result
010: * of using the Program. In no event will IBM be liable for any
011: * special, indirect or consequential damages or lost profits even if
012: * IBM has been advised of the possibility of their occurrence. IBM
013: * will not be liable for any third party claims against you.
014: */
015: import java.net.*;
016: import java.util.*;
017:
018: import org.w3c.dom.*;
019:
020: import com.ibm.webdav.impl.*;
021:
022: /** A Collection is a Resource that contains other
023: * resources including other Collections. It provides a
024: * concrete, client side implementation of Collection.
025: * @author Jim Amsden <jamsden@us.ibm.com>
026: */
027: public class Collection extends Resource {
028:
029: /** shallow means copy just this resource. */
030: public static final String shallow = "0";
031: /** deep means copy this resource and recursively all its members. */
032: public static final String deep = "infinity";
033:
034: /** thisResource means get properties on this resource only. */
035: public static final String this Resource = "0";
036: /** immediateMembers means get properties on this resource and its
037: immediate members. */
038: public static final String immediateMembers = "1";
039: /** allMembers means get properties on this resource and recursively
040: all its members. */
041: public static final String allMembers = "infinity";
042:
043: private Vector members = null; // lazy retrieve the members of the collection for the server
044:
045: public Collection() {
046: super ();
047: }
048:
049: /** Construct a Collection with the given URL. This is the constructor most clients
050: * will use to construct and access collections using WebDAV. The collection having
051: * the url may not exist as this constructor does not access the resource from
052: * the server. Use exists() or attmept to get the members of the collection to
053: * see if it exists. Other constructors are provided using parameters for the
054: * various parts of the URL. See java.net.URLConnection.
055: *
056: * @param url the URL of the resource.
057: * @exception com.ibm.webdav.WebDAVException
058: */
059: public Collection(String url) throws WebDAVException {
060: try {
061: initialize(new URL(url), null);
062: } catch (java.io.IOException exc) {
063: throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST,
064: "Bad URL");
065: }
066: }
067:
068: /** Construct a Collection with the given URL. The resource having
069: * the url may not exist as this constructor does not access the resource from
070: * the server. Use exists() or attmept to get the contents of the resource to
071: * see if it exists. Other constructors are provided using parameters for the
072: * various parts of the URL. See java.net.URLConnection for details. A ResourceFactory
073: * may also be used to construct instances of a Resource.
074: *
075: * @param url the URL of the resource.
076: * @param targetSelector the revision target selector for this Collection
077: * @exception com.ibm.webdav.WebDAVException
078: * @see URLConnection
079: * @see com.ibm.webdav.ResourceFactory
080: */
081: public Collection(String url, TargetSelector targetSelector)
082: throws WebDAVException {
083: try {
084: initialize(new URL(url), targetSelector);
085: } catch (java.io.IOException exc) {
086: throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST,
087: "Bad URL");
088: }
089: }
090:
091: /** Create a Collection from the given URL components.
092: * @param protocol the protocol to use, http:, rmi:, or iiop:
093: * @param host the name or IP addres of the server host. Using the client host name,
094: * or 'localhost' without a port uses local access with no RPC or server required.
095: * @param port the TCP port to use. HTTP uses 80 by default.
096: * @param file the resource URL relative to the server including any query string, etc.
097: * @exception com.ibm.webdav.WebDAVException
098: * @see URLConnection
099: * @see com.ibm.webdav.ResourceFactory
100: */
101: public Collection(String protocol, String host, int port,
102: String file) throws WebDAVException {
103: try {
104: initialize(new URL(protocol, host, port, file), null);
105: } catch (java.io.IOException exc) {
106: throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST,
107: "Bad URL");
108: }
109: }
110:
111: /** Create a Collection from the given URL components. This constructor uses the default
112: * HTTP port.
113: * @param protocol the protocol to use, http:, rmi:, or iiop:
114: * @param host the name or IP addres of the server host. Using the client host name,
115: * or 'localhost' without a port uses local access with no RPC or server required.
116: * @param file the resource URL relative to the server including any query string, etc.
117: * @exception com.ibm.WebDAVException
118: * @see URLConnection
119: * @see com.ibm.webdav.ResourceFactory
120: */
121: public Collection(String protocol, String host, String file)
122: throws WebDAVException {
123: try {
124: initialize(new URL(protocol, host, file), null);
125: } catch (java.io.IOException exc) {
126: throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST,
127: "Bad URL");
128: }
129: }
130:
131: /** Construct a Collection with the given URL. The resource having
132: * the url may not exist as this constructor does not access the resource from
133: * the server. Use exists() or attmept to get the contents of the resource to
134: * see if it exists. Other constructors are provided using parameters for the
135: * various parts of the URL. See java.net.URLConnection for details. A ResourceFactory
136: * may also be used to construct instances of a Resource.
137: *
138: * @param url the URL of the resource.
139: * @exception com.ibm.webdav.WebDAVException
140: * @see URLConnection
141: * @see com.ibm.webdav.ResourceFactory
142: */
143: public Collection(URL url) throws WebDAVException {
144: try {
145: initialize(url, null);
146: } catch (java.io.IOException exc) {
147: throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST,
148: "Bad URL");
149: }
150: }
151:
152: /** Construct a Collection with the given URL. The resource having
153: * the url may not exist as this constructor does not access the resource from
154: * the server. Use exists() or attmept to get the contents of the resource to
155: * see if it exists. Other constructors are provided using parameters for the
156: * various parts of the URL. See java.net.URLConnection for details. A ResourceFactory
157: * may also be used to construct instances of a Resource.
158: *
159: * @param url the URL of the resource.
160: * @param targetSelector the revision target selector for this Collection
161: * @exception com.ibm.webdav.WebDAVException
162: * @see URLConnection
163: * @see com.ibm.webdav.ResourceFactory
164: */
165: public Collection(URL url, TargetSelector targetSelector)
166: throws WebDAVException {
167: try {
168: initialize(url, targetSelector);
169: } catch (java.io.IOException exc) {
170: throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST,
171: "Bad URL");
172: }
173: }
174:
175: /** Construct a Collection with the given URL specification in the given context.
176: * The resource having
177: * the url may not exist as this constructor does not access the resource from
178: * the server. Use exists() or attmept to get the contents of the resource to
179: * see if it exists. Other constructors are provided using parameters for the
180: * various parts of the URL. See java.net.URLConnection for details. A ResourceFactory
181: * may also be used to construct instances of a Collection.
182: *
183: * @param context a URL giving the context in which the spec is evaluated
184: * @param spec a URL whose missing parts are provided by the context
185: * @exception com.ibm.webdav.Exception
186: * @see URLConnection
187: * @see com.ibm.webdav.ResourceFactory
188: */
189: public Collection(URL context, String spec) throws WebDAVException {
190: try {
191: initialize(new URL(context, spec), null);
192: } catch (java.io.IOException exc) {
193: throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST,
194: "Bad URL");
195: }
196: }
197:
198: /**
199: * Put this collection under baseline control.
200: */
201: public void baseline() throws WebDAVException {
202: }
203:
204: /** Deep copy this resource to the destination URL overwriting any existing contents.
205: * All live properties must remain live at the destination server.
206: * Partial results are possible, check the returned status for details.
207: *
208: * @param destinationURL the destination
209: *
210: * @return the status of the copy operation for each resource copied
211: * @exception com.ibm.webdav.WebDAVException
212: */
213: public MultiStatus copy(String destinationURL)
214: throws WebDAVException {
215: return copy(destinationURL, true, null, Collection.deep);
216: }
217:
218: /** Deep copy this resource to the destination URL.
219: * Partial results are possible, check the returned status for details.
220: *
221: * @param destinationURL the destination
222: * @param overwrite true implies overwrite the destination if it exists
223: * @param propertiesToCopy a collection of properties that must be copied or
224: * the method will fail. propertiesToCopy may have one of the following values:
225: * <ul>
226: * <li>null - ignore properties that cannot be copied</li>
227: * <li>empty collection - all properties must be copied or the method will fail</li>
228: * <li>a collection of URIs - a list of the properties that must be copied
229: * or the method will fail</li>
230: * </ul>
231: *
232: * @return the status of the copy operation for each resource copied
233: * @exception com.ibm.webdav.WebDAVException
234: */
235: public MultiStatus copy(String destinationURL, boolean overwrite,
236: Vector propertiesToCopy) throws WebDAVException {
237: return copy(destinationURL, overwrite, propertiesToCopy,
238: Collection.deep);
239: }
240:
241: /** Copy this resource to the destination URL.
242: * Partial results are possible, check the returned status for details.
243: *
244: * @param destinationURL the destination
245: * @param overwrite true implies overrite the destination if it exists
246: * @param propertiesToCopy a collection of properties that must be copied or
247: * the method will fail. propertiesToCopy may have one of the following values:
248: * <ul>
249: * <li>null - ignore properties that cannot be copied</li>
250: * <li>empty collection - all properties must be copied or the method will fail</li>
251: * <li>a collection of URIs - a list of the properties that must be copied
252: * or the method will fail</li>
253: * @param depth an indicator for immediate members or recursively all children.
254: * </ul>
255: * <ul>
256: * <li>shallow: copy only this resource</li>
257: * <li>deep: copy this resource and recursively all of its children</li>
258: * </ul>
259: *
260: * @return the status of the copy operation for each resource copied
261: * @exception com.ibm.webdav.WebDAVException
262: */
263: public MultiStatus copy(String destinationURL, boolean overwrite,
264: Vector propertiesToCopy, String depth)
265: throws WebDAVException {
266: flushCaches();
267: return ((IRCollection) impl).copy(context, destinationURL,
268: overwrite, propertiesToCopy, depth);
269: }
270:
271: /** Actually create the collection in the repository. The resource indicated
272: * by the URL must not already exist. All ancestors of this URL must already
273: * exist.
274: * @exception com.ibm.webdav.WebDAVException
275: */
276: public void createCollection() throws WebDAVException {
277: createCollection((Document) null);
278: }
279:
280: /** Actually create the collection in the repository. The resource indicated
281: * by the URL must not already exist. All ancestors of this URL must already
282: * exist.
283: *
284: * @param contents an XML Document describing the members of this collection, bodies
285: * of members, and properties on the collections or members. Not completely defined in
286: * version 10 of the WebDAV specification
287: *
288: * @return Multistatus describing the result
289: * of the operation
290: * @exception com.ibm.webdav.WebDAVException
291: */
292: public MultiStatus createCollection(Document contents)
293: throws WebDAVException {
294: MultiStatus result = null;
295: result = ((IRCollection) impl).createCollection(context,
296: contents);
297: return result;
298: }
299:
300: /** Create a sub-collection of this collection. The resource indicated
301: * by the URL must not already exist. All ancestors of this URL must already
302: * exist.
303: * @param collectionName the name of the collection to create relative to the
304: * URL of this resource.
305: * @return the newly created Collection
306: * @exception com.ibm.webdav.WebDAVException
307: */
308: public Collection createSubCollection(String collectionName)
309: throws WebDAVException {
310: Collection subCollection = null;
311: try {
312: subCollection = new Collection(getURL().toString()
313: + collectionName);
314: } catch (WebDAVException exc) {
315: throw exc;
316: }
317: subCollection.getRequestContext().precondition(
318: getRequestContext().precondition());
319: subCollection.getRequestContext().authorization(
320: getRequestContext().authorization());
321: subCollection.createCollection();
322: return subCollection;
323: }
324:
325: /** Flush any caches so that subsequent methods obtain fresh data from the server. Currently,
326: * only the contents of the resource and members of a resource collection are cached.
327: * @exception com.ibm.webdav.WebDAVException
328: */
329: public void flushCaches() throws WebDAVException {
330: super .flushCaches();
331: members = null;
332: }
333:
334: /** Get the members of this Collection.
335: *
336: * @return a Vector of CollectionMembers
337: * @exception com.ibm.webdav.WebDAVException
338: */
339: public Vector getMembers() throws WebDAVException {
340: if (members == null) {
341: members = new Vector();
342: MultiStatus multiStatus = getProperties(Collection.immediateMembers);
343: URL this URLu = getURL();
344: String this URL = this URLu.toString();
345:
346: // each response contains a reference to an element in the collection
347: Enumeration responses = multiStatus.getResponses();
348: while (responses.hasMoreElements()) {
349: PropertyResponse response = ((Response) responses
350: .nextElement()).toPropertyResponse();
351: String memberName = response.getResource();
352: URL uu = null;
353: try {
354: uu = new URL(this URLu, memberName);
355: } catch (java.net.MalformedURLException exc) {
356: throw new WebDAVException(
357: WebDAVStatus.SC_BAD_REQUEST,
358: "Malformed URL");
359: }
360: memberName = uu.toString();
361: // don't put myself in my own collection
362: if (!memberName.equals(this URL)) {
363: Resource resource = null;
364: // resource might contain a URI rather than a URL, but
365: // the Resource*P constructors need a full URL, so
366: // we construct one here.
367: try {
368: URL urll = new URL(getURL(), response
369: .getResource());
370: if (response.isOnACollection()) {
371: resource = new Collection(urll);
372: } else {
373: resource = new Resource(urll);
374: }
375: } catch (Exception exc) {
376: throw new WebDAVException(
377: WebDAVStatus.SC_BAD_REQUEST,
378: "Malformed URL");
379: }
380: MultiStatus childProperties = new MultiStatus();
381: childProperties.addResponse(response);
382: CollectionMember member = new CollectionMember(
383: this , resource, childProperties);
384: members.addElement(member);
385: }
386: }
387: }
388: return members;
389: }
390:
391: /** Get the named properties for this resource and (potentially) its children.
392: *
393: * @param names an arrary of property names to retrieve.
394: * @param depth an indicator for immediate members or recursively all children.
395: * <ul>
396: * <li>immediateMembers: propeprties of this resource and its immediate children</li>
397: * <li>allMembers: properties of this resource and recursively all its children</li>
398: * </ul>
399: *
400: * @return a MultiStatus of PropertyResponses
401: * @exception com.ibm.webdav.WebDAVException
402: */
403: public MultiStatus getProperties(PropertyName names[], String depth)
404: throws WebDAVException {
405: return ((IRCollection) impl).getProperties(context, names,
406: depth);
407: }
408:
409: /** Get all the properties for this resource and (potentially) its children.
410: *
411: * @param depth an indicator for immediate members or recursively all children.
412: * <ul>
413: * <li>thisResource: propeprties of this resource</li>
414: * <li>immediateMembers: propeprties of this resource and its immediate children</li>
415: * <li>allMembers: properties of this resource and recursively all its children</li>
416: * </ul>
417: *
418: * @return a MultiStatus of PropertyResponses
419: * @exception com.ibm.webdav.WebDAVException
420: */
421: public MultiStatus getProperties(String depth)
422: throws WebDAVException {
423: return ((IRCollection) impl).getProperties(context, depth);
424: }
425:
426: /** Get the named property for this resource and (potentially) its children.
427: *
428: * @param name the name of the property to retrieve.
429: * @param depth an indicator for immediate members or recursively all children.
430: * <ul>
431: * <li>immediateMembers: propeprties of this resource and its immediate children</li>
432: * <li>allMembers: properties of this resource and recursively all its children</li>
433: * </ul>
434: *
435: * @return a MultiStatus of PropertyResponses
436: * @exception com.ibm.webdav.WebDAVException
437: */
438: public MultiStatus getProperty(PropertyName name, String depth)
439: throws WebDAVException {
440: PropertyName[] names = new PropertyName[1];
441: names[0] = name;
442: return getProperties(names, depth);
443: }
444:
445: /** Get the names of all properties for this resource and (potentially) its children.
446: *
447: * @param depth an indicator for immediate members or recursively all children.
448: * <ul>
449: * <li>thisResource: propeprties of this resource</li>
450: * <li>immediateMembers: propeprties of this resource and its immediate children</li>
451: * <li>allMembers: properties of this resource and recursively all its children</li>
452: * </ul>
453: *
454: * @return a MultiStatus of PropertyResponses
455: * (PropertyValue.value is always null, PropertyValue.status contains the status)
456: * @exception com.ibm.webdav.WebDAVException
457: */
458: public MultiStatus getPropertyNames(String depth)
459: throws WebDAVException {
460: return ((IRCollection) impl).getPropertyNames(context, depth);
461: }
462:
463: /** Initialize this collection instance. Make sure the URL ends in a '/'.
464: */
465: protected void initialize(URL url, TargetSelector targetSelector)
466: throws WebDAVException {
467: String file = url.getFile();
468: if (!file.endsWith("/")) {
469: file = file + "/";
470: }
471: try {
472: this .url = new URL(url, file);
473: impl = ResourceFactory
474: .createCollection(url, targetSelector);
475: } catch (Exception exc) {
476: throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST,
477: "Malformed URL");
478: }
479: }
480:
481: /** Lock this resource collection and recursively all its members based
482: * on the given parameters. This allows control of the lock scope
483: *(exclusive or shared) the lock type (write), owner information, etc.
484: *
485: * @param scope the scope of the lock, exclusive or shared
486: * @param type the type of the lock, currently only write
487: * @param timeout the number of seconds before the lock times out or
488: * 0 for infinite timeout.
489: * @param owner an XML element containing useful information that can be
490: * used to identify the owner of the lock. An href to a home page, an
491: * email address, phone number, etc. Can be null if no owner information
492: * is provided.
493: *
494: * @return a MultiStatus containing a lockdiscovery property indicating
495: * the results of the lock operation.
496: * @exception com.ibm.webdav.WebDAVException
497: */
498: public MultiStatus lock(String scope, String type, int timeout,
499: Element owner) throws WebDAVException {
500: return lock(scope, type, timeout, owner, Collection.deep);
501: }
502:
503: /** Lock this resource based on the given parameters. This allows control of
504: * the lock scope (exclusive or shared) the lock type (write), owner information, etc.
505: *
506: * @param scope the scope of the lock, exclusive or shared
507: * @param type the type of the lock, currently only write
508: * @param timeout the number of seconds before the lock times out or
509: * 0 for infinite timeout.
510: * @param owner an XML element containing useful information that can be
511: * used to identify the owner of the lock. An href to a home page, an
512: * email address, phone number, etc. Can be null if no owner information
513: * is provided.
514: * @param depth
515: * <ul>
516: * <li>shallow lock only this resource</li>
517: * <li>deep lock this resource and all its children</li>
518: * </ul>
519: *
520: * @return a MultiStatus containing a lockdiscovery property indicating
521: * the results of the lock operation.
522: * @exception com.ibm.webdav.WebDAVException
523: */
524: public MultiStatus lock(String scope, String type, int timeout,
525: Element owner, String depth) throws WebDAVException {
526: return ((IRCollection) impl).lock(context, scope, type,
527: timeout, owner, depth);
528: }
529: }
|