001: /*
002: * The contents of this file are subject to the
003: * Mozilla Public License Version 1.1 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
009: * See the License for the specific language governing rights and
010: * limitations under the License.
011: *
012: * The Initial Developer of the Original Code is Simulacra Media Ltd.
013: * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
014: *
015: * All Rights Reserved.
016: *
017: * Contributor(s):
018: */
019:
020: package org.openharmonise.dav.server.managers;
021:
022: import com.ibm.webdav.*;
023: import com.ibm.webdav.impl.*;
024:
025: import java.util.*;
026: import java.util.logging.*;
027: import java.util.logging.Level;
028:
029: import javax.xml.parsers.*;
030:
031: import org.openharmonise.commons.dsi.*;
032: import org.openharmonise.dav.server.utils.*;
033: import org.openharmonise.dav.server.utils.HarmoniseNameResolver;
034: import org.openharmonise.rm.dsi.DataStoreInterfaceFactory;
035: import org.openharmonise.rm.resources.users.*;
036: import org.w3c.dom.*;
037:
038: /**
039: * Harmonise implementation of <code>LockManager</code> to provide DAV4J with
040: * access to locking functionality of the Harmonise repository.
041: *
042: * @author Michael Bell
043: * @version $Revision: 1.2 $
044: *
045: */
046: public class HarmoniseLockManager implements
047: com.ibm.webdav.impl.LockManager {
048: private ResourceImpl resource = null;
049: private com.ibm.webdav.impl.PropertiesManager propertiesManager = null;
050: private AbstractDataStoreInterface m_dsi = null;
051:
052: private static final Logger m_logger = Logger
053: .getLogger(HarmoniseLockManager.class.getName());
054:
055: public HarmoniseLockManager() {
056: }
057:
058: /** Create a lock manager for the given resource.
059: * @param resource the resource to manage locks for
060: * @param namespaceManager its namespace manager
061: * @param propertiesManager and its properties manager
062: */
063: public HarmoniseLockManager(ResourceImpl resource,
064: com.ibm.webdav.impl.NamespaceManager namespaceManager,
065: com.ibm.webdav.impl.PropertiesManager propertiesManager) {
066: initialize(resource, namespaceManager, propertiesManager);
067: }
068:
069: /** Get the lockdiscovery DAV property for the resource.
070: *
071: * @return an Element with tag name D:lockdiscovery
072: * @exception com.ibm.webdav.WebDAVException
073: */
074: public Element getLockDiscovery() throws WebDAVException {
075: // get the raw properties from the property manager
076: Document propertiesDocument = propertiesManager
077: .loadProperties();
078: Element properties = propertiesDocument.getDocumentElement();
079: Element lockdiscovery = (Element) ((Element) properties)
080: .getElementsByTagNameNS("DAV:", "lockdiscovery")
081: .item(0);
082:
083: // timeout any expired locks by
084: // deleting any locks that have timed out
085: boolean locksHaveChanged = false;
086:
087: if (lockdiscovery != null) {
088: NodeList locks = ((Element) lockdiscovery)
089: .getElementsByTagNameNS("DAV:", "activelock");
090: Element lock = null;
091: Date now = new Date();
092:
093: for (int i = 0; i < locks.getLength(); i++) {
094: lock = (Element) locks.item(i);
095:
096: ActiveLock activeLock = new ActiveLock(lock);
097:
098: // see if the lock has timed out
099: Date expiration = activeLock.getExpiration();
100:
101: if ((expiration != null) && expiration.before(now)) {
102: // has timed out, remove the lock
103: locksHaveChanged = true;
104:
105: try {
106: lockdiscovery.removeChild(lock);
107: } catch (Exception exc) {
108: m_logger.log(Level.WARNING, exc
109: .getLocalizedMessage(), exc);
110: }
111: }
112: }
113: }
114:
115: if (locksHaveChanged) {
116: propertiesManager.saveProperties(propertiesDocument);
117: }
118:
119: return lockdiscovery;
120: }
121:
122: /** Get the locks that exist on this resource. May be null if the resource
123: * is not locked.
124: *
125: * @return a Vector of ActiveLock objects
126: * @exception com.ibm.webdav.WebDAVException
127: */
128: public Vector getLocks() throws WebDAVException {
129: Element lockdiscovery = (Element) getLockDiscovery();
130: Vector allLocks = new Vector();
131:
132: if (lockdiscovery != null) {
133: NodeList activeLocks = ((Element) lockdiscovery)
134: .getElementsByTagNameNS("DAV:", "activelock");
135: Element activeLock = null;
136:
137: for (int i = 0; i < activeLocks.getLength(); i++) {
138: activeLock = (Element) activeLocks.item(i);
139: allLocks.addElement(new ActiveLock(activeLock));
140: }
141: }
142:
143: return allLocks;
144: }
145:
146: /** Get information about locks supported by this resource.
147: *
148: * @return an Element with tag name D:supportedlock
149: */
150: public Element getSupportedLock() {
151: org.w3c.dom.Document document = null;
152:
153: try {
154: document = DocumentBuilderFactory.newInstance()
155: .newDocumentBuilder().newDocument();
156: } catch (Exception e) {
157: m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
158: }
159:
160: Element supportedlock = document.createElementNS("DAV:",
161: "D:supportedlock");
162:
163: Element lockentry = document.createElementNS("DAV:",
164: "D:lockentry");
165:
166: supportedlock.appendChild(lockentry);
167:
168: Element lockscope = document.createElementNS("DAV:",
169: "D:lockscope");
170:
171: Element lockexclusive = document.createElementNS("DAV:",
172: "D:exclusive");
173:
174: lockscope.appendChild(lockexclusive);
175: lockentry.appendChild(lockscope);
176:
177: Element locktype = document.createElementNS("DAV:",
178: "D:locktype");
179:
180: Element lockwrite = document.createElementNS("DAV:", "D:write");
181:
182: locktype.appendChild(lockwrite);
183: lockentry.appendChild(locktype);
184: lockentry = document.createElementNS("DAV:", "D:lockentry");
185:
186: supportedlock.appendChild(lockentry);
187: lockscope = document.createElementNS("DAV:", "D:lockscope");
188:
189: Element lockshare = document
190: .createElementNS("DAV:", "D:shared");
191:
192: lockscope.appendChild(lockshare);
193: lockentry.appendChild(lockscope);
194: locktype = document.createElementNS("DAV:", "D:locktype");
195:
196: lockwrite = document.createElementNS("DAV:", "D:write");
197:
198: locktype.appendChild(lockwrite);
199: lockentry.appendChild(locktype);
200:
201: return supportedlock;
202: }
203:
204: /** Initialize an this LockManager instance.
205: * @param resource the resource to manage locks for
206: * @param namespaceManager its namespace manager
207: * @param propertiesManager its properties manager
208: */
209: public void initialize(ResourceImpl resource,
210: com.ibm.webdav.impl.NamespaceManager namespaceManager,
211: com.ibm.webdav.impl.PropertiesManager propertiesManager) {
212: this .resource = resource;
213: this .propertiesManager = propertiesManager;
214:
215: try {
216: this .m_dsi = DataStoreInterfaceFactory
217: .getDataStoreInterface();
218: } catch (Exception e) {
219: throw new RuntimeException(
220: "Datastore interface not started properly.");
221: }
222: }
223:
224: /** Lock this resource Using the given activeLock.
225: *
226: * @param activeLock the lock to activate (i.e., persist)
227: *
228: * @return a MultiStatus containing a lockdiscovery property indicating
229: * the results of the lock operation.
230: * @exception com.ibm.webdav.WebDAVException
231: */
232: public MultiStatus lock(ActiveLock activeLock)
233: throws WebDAVException {
234: String lockToken = "";
235:
236: try {
237: lockToken = getLockToken(resource.getURL().getFile(),
238: resource.getContext().getRequestContext()
239: .getAuthorizationId());
240: } catch (Exception e) {
241: m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
242: throw new WebDAVException(
243: WebDAVStatus.SC_INTERNAL_SERVER_ERROR,
244: "Had trouble getting UUID");
245: }
246:
247: activeLock.setLockToken(lockToken);
248:
249: try {
250: User usr = ((HarmoniseSessionManager) resource
251: .getUserAuthenticator()).getUser(resource);
252:
253: activeLock.setOwner(HarmoniseNameResolver.getDAVPath(usr));
254: } catch (WebDAVException e) {
255: throw new WebDAVException(
256: WebDAVStatus.SC_INTERNAL_SERVER_ERROR, e
257: .getLocalizedMessage());
258: } catch (NameResolverException e) {
259: throw new WebDAVException(
260: WebDAVStatus.SC_INTERNAL_SERVER_ERROR, e
261: .getLocalizedMessage());
262: }
263:
264: Element alockEl = activeLock.asXML();
265:
266: org.w3c.dom.Document xmlDoc = alockEl.getOwnerDocument();
267: MultiStatus result = new MultiStatus();
268: PropertyResponse propertyResponse = new PropertyResponse(
269: resource.getURL().toString());
270: result.addResponse(propertyResponse);
271:
272: PropertyValue l = resource
273: .getProperty(PropertyName.pnLockdiscovery);
274: Element lockdiscovery = null;
275:
276: if (l == null) {
277: lockdiscovery = xmlDoc.createElementNS("DAV:",
278: "D:lockdiscovery");
279:
280: lockdiscovery.setAttribute("xmlns:D", "DAV:");
281: } else {
282: lockdiscovery = (Element) ((Element) l.value)
283: .cloneNode(true);
284: }
285:
286: Element lockEl = (Element) lockdiscovery.getOwnerDocument()
287: .importNode(alockEl, true);
288:
289: lockdiscovery.appendChild(lockEl);
290: propertiesManager.setProperty("DAV:lockdiscovery",
291: lockdiscovery);
292:
293: // all lock methods return the lockdiscovery property, even if the lock failed
294: PropertyName propname = PropertyName
295: .createPropertyNameQuietly("DAV:lockdiscovery");
296:
297: propertyResponse.addProperty(propname,
298: (Element) ((Element) lockdiscovery).cloneNode(true),
299: WebDAVStatus.SC_OK);
300:
301: return result;
302: }
303:
304: static public String getLockToken(String sFilename, String sUser)
305: throws NameResolverException {
306: return "hislocktoken:"
307: + HarmoniseNameResolver.getUUID(sFilename, sUser);
308: }
309:
310: /**
311: * Refresh the lock on this resource by resetting the lock timeout.
312: * The context must contain the proper authorization for the requesting
313: * principal.
314: *
315: * @param activeLock the lock to refresh. Contains the updated timeout
316: * and expiration date.
317: *
318: * @return updated information about the lock status of this resource
319: * @exception com.ibm.webdav.WebDAVException
320: */
321: public MultiStatus refreshLock(ActiveLock activeLock)
322: throws WebDAVException {
323: Element alockEl = activeLock.asXML();
324: org.w3c.dom.Document xmlDoc = alockEl.getOwnerDocument();
325:
326: MultiStatus result = new MultiStatus();
327: PropertyResponse propertyResponse = new PropertyResponse(
328: resource.getURL().toString());
329: result.addResponse(propertyResponse);
330:
331: // get the locks on this resource
332: PropertyValue l = resource
333: .getProperty(PropertyName.pnLockdiscovery);
334: Element lockdiscovery = null;
335:
336: if (l == null) {
337: lockdiscovery = xmlDoc.createElementNS("DAV:",
338: "D:lockdiscovery");
339:
340: lockdiscovery.setAttribute("xmlns:D", "DAV:");
341: } else {
342: lockdiscovery = (Element) ((Element) l.value)
343: .cloneNode(true);
344: }
345:
346: // find the lock
347: boolean lockFound = false;
348: NodeList locks = ((Element) lockdiscovery)
349: .getElementsByTagNameNS("DAV:", "activelock");
350: Element lock = null;
351:
352: for (int i = 0; i < locks.getLength(); i++) {
353: lock = (Element) locks.item(i);
354:
355: ActiveLock aLock = new ActiveLock(lock);
356:
357: if (aLock.getLockToken().equals(activeLock.getLockToken())) {
358: lockFound = true;
359: lockdiscovery.removeChild(lock);
360:
361: break;
362: }
363: }
364:
365: if (!lockFound) {
366: throw new WebDAVException(
367: WebDAVStatus.SC_PRECONDITION_FAILED,
368: "principal does not own a lock");
369: }
370:
371: lockdiscovery.appendChild(alockEl);
372: propertiesManager.setProperty("DAV:lockdiscovery",
373: lockdiscovery);
374:
375: PropertyName propname = PropertyName
376: .createPropertyNameQuietly("DAV:lockdiscovery");
377:
378: // all lock methods return the lockdiscovery property, even if the lock failed
379: propertyResponse.addProperty(propname,
380: (Element) ((Element) lockdiscovery).cloneNode(true),
381: WebDAVStatus.SC_OK);
382:
383: return result;
384: }
385:
386: /** Unlock the lock identified by the lockToken on this resource
387: *
388: * @param activeLock the lock to unlock
389: *
390: * @return a MultiStatus containing any responses on resources that could not
391: * be unlocked.
392: * @exception com.ibm.webdav.WebDAVException
393: */
394: public MultiStatus unlock(ActiveLock activeLock)
395: throws WebDAVException {
396: Element alockEl = activeLock.asXML();
397: org.w3c.dom.Document xmlDoc = alockEl.getOwnerDocument();
398:
399: MultiStatus result = new MultiStatus();
400: PropertyResponse propertyResponse = new PropertyResponse(
401: resource.getURL().toString());
402: result.addResponse(propertyResponse);
403:
404: // get the locks on this resource
405: PropertyValue l = resource
406: .getProperty(PropertyName.pnLockdiscovery);
407: Element lockdiscovery = null;
408:
409: if (l == null) {
410: lockdiscovery = xmlDoc.createElementNS("DAV:",
411: "D:lockdiscovery");
412:
413: lockdiscovery.setAttribute("xmlns:D", "DAV:");
414: } else {
415: lockdiscovery = (Element) ((Element) l.value)
416: .cloneNode(true);
417: }
418:
419: // find the lock
420: ActiveLock lockToRemove = null;
421: NodeList locks = ((Element) lockdiscovery)
422: .getElementsByTagNameNS("DAV:", "activelock");
423: Element lock = null;
424:
425: for (int i = 0; i < locks.getLength(); i++) {
426: lock = (Element) locks.item(i);
427:
428: ActiveLock aLock = new ActiveLock(lock);
429:
430: if (aLock.getLockToken().equals(activeLock.getLockToken())) {
431: lockToRemove = aLock;
432: lockdiscovery.removeChild(lock);
433:
434: break;
435: }
436: }
437:
438: if (lockToRemove == null) {
439: throw new WebDAVException(
440: WebDAVStatus.SC_PRECONDITION_FAILED,
441: "resource is not locked with the given lock token");
442: } else {
443: propertiesManager.setProperty("DAV:lockdiscovery",
444: lockdiscovery);
445: }
446:
447: // all lock methods return the lockdiscovery property, even if the lock failed
448: PropertyName propname = PropertyName
449: .createPropertyNameQuietly("DAV:lockdiscovery");
450: propertyResponse.addProperty(propname,
451: (Element) ((Element) lockdiscovery).cloneNode(true),
452: WebDAVStatus.SC_OK);
453:
454: return result;
455: }
456: }
|