KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > slide > webdav > method > PropPatchMethod


1 /*
2  * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PropPatchMethod.java,v 1.86 2004/08/03 09:37:48 ozeigermann Exp $
3  * $Revision: 1.86 $
4  * $Date: 2004/08/03 09:37:48 $
5  *
6  * ====================================================================
7  *
8  * Copyright 1999-2002 The Apache Software Foundation
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */

23
24 package org.apache.slide.webdav.method;
25
26 import java.io.IOException JavaDoc;
27 import java.io.Writer JavaDoc;
28 import java.util.Date JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.StringTokenizer JavaDoc;
32
33 import org.apache.slide.common.NamespaceAccessToken;
34 import org.apache.slide.common.PropertyParseException;
35 import org.apache.slide.common.RequestedPropertiesImpl;
36 import org.apache.slide.common.RequestedProperty;
37 import org.apache.slide.common.RequestedPropertyImpl;
38 import org.apache.slide.common.ServiceAccessException;
39 import org.apache.slide.content.NodeProperty;
40 import org.apache.slide.content.NodeRevisionDescriptor;
41 import org.apache.slide.content.NodeRevisionDescriptors;
42 import org.apache.slide.content.NodeRevisionNumber;
43 import org.apache.slide.content.RevisionDescriptorNotFoundException;
44 import org.apache.slide.content.NodeProperty.NamespaceCache;
45 import org.apache.slide.event.EventDispatcher;
46 import org.apache.slide.structure.LinkedObjectNotFoundException;
47 import org.apache.slide.util.Configuration;
48 import org.apache.slide.util.XMLValue;
49 import org.apache.slide.webdav.WebdavException;
50 import org.apache.slide.webdav.WebdavServletConfig;
51 import org.apache.slide.webdav.event.WebdavEvent;
52 import org.apache.slide.webdav.util.AclConstants;
53 import org.apache.slide.webdav.util.DeltavConstants;
54 import org.apache.slide.webdav.util.PreconditionViolationException;
55 import org.apache.slide.webdav.util.PropertyHelper;
56 import org.apache.slide.webdav.util.UriHandler;
57 import org.apache.slide.webdav.util.VersioningHelper;
58 import org.apache.slide.webdav.util.ViolatedPrecondition;
59 import org.apache.slide.webdav.util.WebdavStatus;
60 import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind;
61 import org.apache.slide.webdav.util.resourcekind.CheckedInVersionControlled;
62 import org.apache.slide.webdav.util.resourcekind.ResourceKind;
63 import org.jdom.CDATA;
64 import org.jdom.Comment;
65 import org.jdom.Document;
66 import org.jdom.Element;
67 import org.jdom.EntityRef;
68 import org.jdom.JDOMException;
69 import org.jdom.Namespace;
70 import org.jdom.ProcessingInstruction;
71 import org.jdom.Text;
72 import org.jdom.output.Format;
73 import org.jdom.output.XMLOutputter;
74
75 /**
76  * PROPPATCH method.
77  *
78  */

79 public class PropPatchMethod extends AbstractWebdavMethod implements DeltavConstants, AclConstants, WriteMethod {
80     
81     
82     // -------------------------------------------------------------- Constants
83

84        
85     // ----------------------------------------------------- Instance Variables
86

87     
88     /**
89      * The helpers used by this instance.
90      */

91     protected VersioningHelper versioningHelper = null;
92     protected PropertyHelper propertyHelper = null;
93     
94     /**
95      * Properties to set.
96      */

97     private PropPatchProperties propertiesToSet;
98     
99     /**
100      * Properties to remove.
101      */

102     private PropPatchProperties propertiesToRemove;
103     
104     /**
105      * Resource which will have its properties updated.
106      */

107     private String JavaDoc resourcePath;
108     
109     /**
110      * If true, the last modified date will be updated.
111      */

112     private boolean updateLastModified;
113     
114     // ----------------------------------------------------------- Constructors
115

116     
117     /**
118      * Constructor.
119      *
120      * @param token the token for accessing the namespace
121      * @param config configuration of the WebDAV servlet
122      */

123     public PropPatchMethod(NamespaceAccessToken token,
124                            WebdavServletConfig config) {
125         super(token, config);
126     }
127     
128     
129     // ------------------------------------------------------ Protected Methods
130

131     
132     /**
133      * Parse the request.
134      *
135      * @exception WebdavException Bad request
136      */

137     protected void parseRequest()
138         throws WebdavException {
139         
140         versioningHelper =
141             VersioningHelper.getVersioningHelper( slideToken, token, req, resp, config );
142         propertyHelper =
143             PropertyHelper.getPropertyHelper( slideToken, token, getConfig() );
144         
145 // readRequestContent();
146

147         updateLastModified = getBooleanInitParameter( "updateLastModified" );
148         
149         resourcePath = requestUri;
150         if (resourcePath == null) {
151             resourcePath = "/";
152         }
153         propertiesToSet = new PropPatchProperties();
154         propertiesToRemove = new PropPatchProperties();
155         
156         if (req.getContentLength() != 0) {
157             
158             try {
159                 Iterator JavaDoc childrenIterator = parseRequestContent(E_PROPERTYUPDATE).getChildren().iterator();
160                 Element child = null;
161                 while (childrenIterator.hasNext()) {
162                     child = (Element)childrenIterator.next();
163                     if (E_SET.equals(child.getName())) {
164                         propertiesToSet.add(getPropElement(child));
165                     }
166                     else if (E_REMOVE.equals(child.getName())) {
167                         propertiesToRemove.add(getPropElement(child));
168                     }
169                     else {
170                         throw new JDOMException("Expected <"+E_SET+"> or <"+E_REMOVE+"> element");
171                     }
172                 }
173                 
174                 
175             }
176             catch( Exception JavaDoc e ) {
177                 int statusCode = getErrorCode( e );
178                 sendError( statusCode, e );
179                 throw new WebdavException( statusCode );
180             }
181         }
182         else {
183             int statusCode = WebdavStatus.SC_BAD_REQUEST;
184             sendError( statusCode, getClass().getName()+".missingRequestBody" );
185             throw new WebdavException( statusCode );
186         }
187         
188     }
189     
190     /**
191      * Checks if the given Element has exactly one child named
192      * <code>&lt;prop&gt;</code>. If the check succeeds the
193      * <code>&lt;prop&gt;</code> element is returned, otherwise a
194      * JDOMException is thrown.
195      *
196      * @param parent the parent Element of the <code>&lt;prop&gt;</code>.
197      *
198      * @return the <code>&lt;prop&gt;</code> element.
199      *
200      * @throws JDOMException if the check fails.
201      */

202     private Element getPropElement(Element parent) throws JDOMException {
203         List JavaDoc childrenList = parent.getChildren();
204         if ( (childrenList.size() != 1) ||
205                 ( ! E_PROP.equals(((Element)childrenList.get(0)).getName()) ) ) {
206             throw new JDOMException("Expected &lt;"+E_PROP+"&gt; element");
207         }
208         return (Element)childrenList.get(0);
209     }
210     
211     
212     /**
213      * Execute the request.
214      *
215      * @exception WebdavException
216      */

217     protected void executeRequest()
218         throws WebdavException, IOException JavaDoc {
219         
220         boolean allOperationsExcecuted = true;
221         
222         // Prevent dirty reads
223
slideToken.setForceStoreEnlistment(true);
224         
225         // check lock-null resources
226
try {
227             if (isLockNull(resourcePath)) {
228                 int statusCode = WebdavStatus.SC_NOT_FOUND;
229                 sendError( statusCode, "lock-null resource", new Object JavaDoc[]{resourcePath} );
230                 throw new WebdavException( statusCode );
231             }
232         }
233         catch (ServiceAccessException e) {
234             int statusCode = getErrorCode((Exception JavaDoc)e);
235             sendError( statusCode, e );
236             throw new WebdavException( statusCode );
237         }
238
239         try {
240             if ( WebdavEvent.PROPPATCH.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(WebdavEvent.PROPPATCH, new WebdavEvent(this));
241             
242             VersioningHelper vHelp =
243                 VersioningHelper.getVersioningHelper(slideToken, token, req, resp, getConfig() );
244             NodeRevisionDescriptors revisionDescriptors =
245                 content.retrieve(slideToken, resourcePath);
246             
247             NodeRevisionNumber revisionNumber =
248                 revisionDescriptors.getLatestRevision();
249             NodeRevisionDescriptor revisionDescriptor = null;
250             if (revisionNumber != null) {
251                 try {
252                     revisionDescriptor = content.retrieve
253                         (slideToken, revisionDescriptors);
254                 } catch (RevisionDescriptorNotFoundException e) {
255                 }
256             }
257             
258             if (revisionDescriptor == null) {
259                 revisionDescriptor = new NodeRevisionDescriptor(0);
260             }
261             
262             ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(token, resourcePath, revisionDescriptor);
263             
264             // check preconditions
265
ViolatedPrecondition violatedPrecondition = getPreconditionViolation(revisionDescriptors, revisionDescriptor, resourceKind);
266             if (violatedPrecondition != null) {
267                 throw new PreconditionViolationException(violatedPrecondition, resourcePath);
268             }
269             
270             // Changed for DeltaV --start--
271
boolean mustCheckIn = false;
272             if( Configuration.useVersionControl() &&
273                    (resourceKind instanceof CheckedInVersionControlled) &&
274                versioningHelper.mustCheckoutAutoVersionedVCR(revisionDescriptors, revisionDescriptor) ) {
275                 
276                 vHelp.checkout(revisionDescriptors, revisionDescriptor, false, false, true );
277                 mustCheckIn = versioningHelper.mustCheckinAutoVersionedVCR(slideToken, revisionDescriptors, revisionDescriptor);
278             }
279             
280             // Modifying the properties
281

282             Iterator JavaDoc propertyIterator = null;
283             
284             propertyIterator = propertiesToSet.iterator();
285             PropPatchProperty currentProperty = null;
286             while (propertyIterator.hasNext()) {
287                 
288                 currentProperty = (PropPatchProperty)propertyIterator.next();
289                 if (checkPropertyModification(currentProperty, revisionDescriptor, resourceKind)) {
290                     // Convert absolute URIs to relative ones, because Slide
291
// converts them to absolute ones in the result of queries.
292
String JavaDoc finalValue = currentProperty.getValue();
293                     Element property = new Element(currentProperty.getName(), currentProperty.getNamespace());
294                     String JavaDoc propertyValue = currentProperty.getValue();
295                     if ( (propertyValue != null) && (propertyValue.toString().length() > 0)) {
296                         if( propertyValue.toString().indexOf('<') >= 0 ) {
297                             try {
298                                 XMLValue xmlValue = new XMLValue(propertyValue.toString(), Namespace.getNamespace(currentProperty.getNamespace()));
299                                 if (AbstractResourceKind.isLiveProperty(currentProperty.getName())) {
300                                     convertHrefValueToRelativeURL (xmlValue, getSlideContextPath(), config);
301                                 }
302                                 Iterator JavaDoc iterator = xmlValue.iterator();
303                                 while (iterator.hasNext()) {
304                                     Object JavaDoc o = iterator.next();
305                                     if( o instanceof Element )
306                                         property.addContent((Element)o);
307                                     else if( o instanceof Text )
308                                         property.addContent((Text)o);
309                                     else if( o instanceof Comment )
310                                         property.addContent((Comment)o);
311                                     else if( o instanceof ProcessingInstruction )
312                                         property.addContent((ProcessingInstruction)o);
313                                     else if( o instanceof CDATA )
314                                         property.addContent((CDATA)o);
315                                     else if( o instanceof EntityRef )
316                                         property.addContent((EntityRef)o);
317                                 }
318                                 finalValue = new XMLOutputter(Format.getRawFormat()).outputString(property.getContent());
319                             }
320                             catch (JDOMException e) {
321                                 // Fallback to original value
322
}
323                         }
324                     }
325                     NodeProperty newProperty =
326                         new NodeProperty(currentProperty.getName(),
327                                          finalValue,
328                                          currentProperty.getNamespace());
329                     revisionDescriptor.setProperty(newProperty);
330                     
331                 }
332                 else {
333                     allOperationsExcecuted = false;
334                 }
335             }
336             
337             propertyIterator = propertiesToRemove.iterator();
338             while (propertyIterator.hasNext()) {
339                 
340                 currentProperty = (PropPatchProperty)propertyIterator.next();
341                 if (checkPropertyModification(currentProperty, revisionDescriptor, resourceKind)) {
342                     revisionDescriptor.removeProperty(currentProperty.getName(),
343                                                       currentProperty.getNamespace());
344                 }
345                 else {
346                     allOperationsExcecuted = false;
347                 }
348                 
349             }
350             
351             if (updateLastModified) {
352                 revisionDescriptor.setLastModified(new Date JavaDoc());
353             }
354             
355             if (allOperationsExcecuted) {
356                 content.store(slideToken, resourcePath, revisionDescriptor, null);
357             }
358             
359             // Changed for DeltaV --start--
360
if( Configuration.useVersionControl() && mustCheckIn) {
361                 vHelp.checkin(revisionDescriptors, revisionDescriptor, false, false, true ); //forkOk=false, keepCheckedOut=false
362
}
363             // Changed for DeltaV --end--
364

365             resp.setContentType(TEXT_XML_UTF_8);
366             
367             resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
368             
369         }
370         catch (PreconditionViolationException e) {
371             sendPreconditionViolation(e);
372             throw e;
373         }
374         catch (Exception JavaDoc e) {
375             int statusCode = getErrorCode( e );
376             sendError( statusCode, e );
377             throw new WebdavException( statusCode );
378         }
379         
380         
381         // No serious errors. Printing the XML report.
382
writeReport();
383         
384         if (!allOperationsExcecuted) {
385             throw new WebdavException( WebdavStatus.SC_ACCEPTED ); // abort the TA
386
}
387         
388     }
389     
390     
391     
392     
393     /**
394      * Get return status based on exception type.
395      */

396     protected int getErrorCode(Exception JavaDoc ex) {
397         try {
398             throw ex;
399         } catch (LinkedObjectNotFoundException e) {
400             return WebdavStatus.SC_NOT_FOUND;
401         } catch (PropertyParseException e) {
402             return WebdavStatus.SC_BAD_REQUEST;
403         } catch (JDOMException e) {
404             return WebdavStatus.SC_BAD_REQUEST;
405         } catch (Exception JavaDoc e) {
406             return super.getErrorCode(e);
407         }
408     }
409     
410     
411     
412     // -------------------------------------------------------- Private Methods
413

414     
415     
416     
417     
418     /**
419      * Check if the property is a live property which should have its value
420      * enforced by the server.
421      *
422      * @param property The property object
423      * @param rd the revision descriptor containing all properties
424      * @param resourceKind the kind of the resource to patch.
425      */

426     private boolean checkPropertyModification(PropPatchProperty property, NodeRevisionDescriptor rd, ResourceKind resourceKind) {
427         
428         boolean result = false;
429         ViolatedPrecondition violatedPrecondition = getPropertySpecificPreconditionViolation(property);
430         if (violatedPrecondition != null) {
431             property.setViolatedPrecondition(violatedPrecondition);
432         }
433         else {
434             NodeProperty originalProperty = rd.getProperty(property.getName(), property.getNamespace());
435             if (originalProperty == null) {
436                 // computed properties can not be modified
437
result = (!AbstractResourceKind.isComputedProperty(property.getName()));
438             }
439             else {
440                 result = !originalProperty.isProtected();
441             }
442             
443             if ( ! result ) {
444                 property.setErrorMessage("Property " + property.getQualifiedNameAsElementString() + " is protected");
445             }
446             
447             if ( result && !isSupportedPropertyValue(property, resourceKind) ) {
448                 property.setErrorMessage("Value " + property.getValue() + " is not supported by property " + property.getQualifiedNameAsElementString());
449                 result = false;
450             }
451             
452             if (!result) property.setStatusCode(WebdavStatus.SC_CONFLICT);
453         }
454         return result;
455     }
456
457     /**
458      * Return <code>true</code> if the given <code>property</code> value is supported
459      * for that property of the <code>resourceKind</code>
460      *
461      * @param property the property to check.
462      * @param resourceKind the ResourceKind.
463      *
464      * @return <code>true</code> if the value is supported.
465      */

466     private boolean isSupportedPropertyValue(PropPatchProperty property, ResourceKind resourceKind) {
467         
468         boolean isSupportedValue = true;
469         if (property.getValue() != null) {
470             
471             if ( ! resourceKind.isSupportedPropertyValue(property.getName(), property.getValue()) ) {
472                 isSupportedValue = false;
473             }
474             
475             if (P_GETCONTENTLANGUAGE.equals(property.getName())) {
476                 
477                 StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(property.getValue(), "-");
478                 String JavaDoc token = null;
479                 while ( isSupportedValue && tokenizer.hasMoreTokens() ) {
480                     token = tokenizer.nextToken();
481                     isSupportedValue = ( (token.length() >= 1) && (token.length() <= 8) );
482                     int i = 0;
483                     while (isSupportedValue && (i < token.length()) ) {
484                         char character = token.charAt(i);
485                         isSupportedValue =
486                             ((character >= 'a') && (character <= 'z')) ||
487                             ((character >= 'A') && (character <= 'Z'));
488                         ++i;
489                     }
490                 }
491             }
492             
493         }
494         return isSupportedValue;
495     }
496     
497     
498     
499     /**
500      * Write the report.
501      */

502     private void writeReport()
503         throws WebdavException {
504         
505         Element multistatus = new Element(E_MULTISTATUS, DNSP);
506         Element response = new Element(E_RESPONSE, DNSP);
507         multistatus.addContent(response);
508         Element href = new Element(E_HREF, DNSP);
509         href.setText(getFullPath(requestUri));
510         response.addContent(href);
511         
512         // Parse the two properties list, and printout their status
513
addPropstatElements(propertiesToSet, response);
514         addPropstatElements(propertiesToRemove, response);
515         
516         try {
517             resp.setContentType(TEXT_XML_UTF_8);
518             Writer JavaDoc writer = resp.getWriter();
519             org.jdom.output.Format format = org.jdom.output.Format.getPrettyFormat();
520             format.setIndent(XML_RESPONSE_INDENT);
521             new XMLOutputter(format).
522                 output(new Document(multistatus), writer);
523             writer.flush();
524         } catch (Exception JavaDoc e) {
525             int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
526             sendError( statusCode, e );
527             throw new WebdavException( statusCode );
528         }
529         
530     }
531     
532     /**
533      * Adds the <code>&lt;propstat&gt;</code> elements for the given
534      * <code>properties</code> to the given <code>&lt;response&gt;</code>
535      * element.
536      *
537      * @param properties the PropPatchProperties for which to add the
538      * <code>&lt;propstat&gt;</code> elements.
539      * @param response the <code>&lt;response&gt;</code> element to add
540      * the <code>&lt;propstat&gt;</code> elements to.
541      */

542     private void addPropstatElements(PropPatchProperties properties, Element response) {
543         
544         Iterator JavaDoc propertyIterator = properties.iterator();
545         while(propertyIterator.hasNext()) {
546             PropPatchProperty property = (PropPatchProperty) propertyIterator.next();
547             Element propstat = createPropstatElement(property);
548             response.addContent(propstat);
549             if (property.getViolatedPrecondition() != null) {
550                 Element responseDescription = new Element(E_RESPONSEDESCRIPTION, DNSP);
551                 responseDescription.addContent(MethodUtil.getPreconditionViolationError(property.getViolatedPrecondition()));
552                 propstat.addContent(responseDescription);
553             }
554             else if (property.getErrorMessage() != null) {
555                 Element responseDescription = new Element(E_RESPONSEDESCRIPTION, DNSP);
556                 responseDescription.addContent(property.getErrorMessage());
557                 propstat.addContent(responseDescription);
558             }
559         }
560     }
561     
562     /**
563      * Creates a <code>&lt;propstat&gt;</code> element for the given
564      * <code>property</code>.
565      *
566      * @param property the PropPatchProperty for which to create a
567      * <code>&lt;propstat&gt;</code> element.
568      *
569      * @return the created <code>&lt;propstat&gt;</code> element.
570      */

571     private Element createPropstatElement(PropPatchProperty property) {
572         
573         Element propstat = new Element(E_PROPSTAT, DNSP);
574         Element prop = new Element(E_PROP, DNSP);
575         propstat.addContent(prop);
576         
577         Namespace namespace = Namespace.NO_NAMESPACE;
578         if (property.getNamespace() != null) {
579             namespace = NamespaceCache.getNamespace(property.getNamespace());
580         }
581         Element propertyElement = new Element(property.getName(), namespace);
582         prop.addContent(propertyElement);
583         
584         Element status = new Element(E_STATUS, DNSP);
585         status.setText("HTTP/1.1 " + property.statusCode + " "
586                            + WebdavStatus.getStatusText(property.statusCode));
587         propstat.addContent(status);
588         return propstat;
589     }
590     
591     /**
592      * Checks the (DeltaV) preconditions
593      * <ul>
594      * <li>&lt;DAV:cannot-modify-version-controlled-property&gt;</li>
595      * <li>&lt;DAV:cannot-modify-version&gt;</li>
596      * <li>&lt;DAV:cannot-modify-protected-property&gt;</li>
597      * <li>&lt;DAV:supported-live-property&gt;</li>
598      * </ul>
599      *
600      * @param revisionDescriptors the NodeRevisionDescriptors of the resource
601      * to perform the <code>PUT</code> on.
602      * @param revisionDescriptor the NodeRevisionDescriptor of the resource
603      * to perform the <code>PUT</code> on.
604      * @param resourceKind the ResourceKind of the resource.
605      *
606      * @return the precondition that has been violated (if any).
607      */

608     private ViolatedPrecondition getPreconditionViolation(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, ResourceKind resourceKind)
609         throws ServiceAccessException {
610         
611         if( Configuration.useVersionControl() ) {
612             
613             if (resourceKind instanceof CheckedInVersionControlled) {
614                 
615                 // check precondition DAV:cannot-modify-version-controlled-property
616
String JavaDoc autoVersion = versioningHelper.getAutoVersionElementName(revisionDescriptor);
617                 if (autoVersion == null) {
618                     autoVersion = "";
619                 }
620                 
621                 if ( !E_CHECKOUT_CHECKIN.equals(autoVersion) &&
622                     !E_CHECKOUT_UNLOCKED_CHECKIN.equals(autoVersion) &&
623                     !E_CHECKOUT.equals(autoVersion) &&
624                     !E_CHECKOUT_IGNORE_UNLOCK.equals(autoVersion) &&
625                     !E_LOCKED_CHECKOUT.equals(autoVersion) ) {
626                     return new ViolatedPrecondition(C_CANNOT_MODIFY_VERSION_CONTROLLED_PROPERTY,
627                                                     WebdavStatus.SC_FORBIDDEN);
628                 }
629                 if (E_LOCKED_CHECKOUT.equals(autoVersion)) {
630                     if ( !versioningHelper.isWriteLocked(slideToken, revisionDescriptors) ) {
631                         return new ViolatedPrecondition(C_CANNOT_MODIFY_VERSION_CONTROLLED_PROPERTY,
632                                                         WebdavStatus.SC_FORBIDDEN);
633                     }
634                 }
635             }
636             
637             // check precondition DAV:cannot-modify-version
638
UriHandler uriHandler = UriHandler.getUriHandler(resourcePath);
639             if (uriHandler.isVersionUri()) {
640                 return new ViolatedPrecondition(C_CANNOT_MODIFY_VERSION,
641                                                 WebdavStatus.SC_FORBIDDEN);
642             }
643         }
644         
645         return null;
646     }
647     
648     /**
649      * Checks the property specific preconditions
650      * <ul>
651      * <li>&lt;DAV:cannot-modify-protected-property&gt;</li>
652      * <li>&lt;DAV:supported-live-property&gt;</li>
653      * </ul>
654      *
655      * @param property the PropPatchProperty to check.
656      *
657      * @return the precondition that has been violated (if any,
658      * otherwise <code>null</code>).
659      */

660     private ViolatedPrecondition getPropertySpecificPreconditionViolation(PropPatchProperty property) {
661         
662         // check precondition DAV:cannot-modify-protected-property
663
if ( AbstractResourceKind.isProtectedProperty(property.getName()) &&
664             DeltavConstants.DELTAV_PROPERTY_LIST.contains(property.getName()) ) {
665             return new ViolatedPrecondition(C_CANNOT_MODIFY_PROTECTED_PROPERTY,
666                                             WebdavStatus.SC_CONFLICT);
667         }
668         
669         // check precondition DAV:supported-live-property
670
// ...is there any property to check here yet ?
671

672         return null;
673     }
674     
675     
676     
677     /**
678      * If the given <code>xmlValue</code> contains <code>&lt;href&gt;</code>
679      * elements (at any depth), absolute URIs are converted to relative ones.
680      *
681      * This method modifies <code>xmlValue</code> (and its children).
682      *
683      * @param xmlValue The XMLValue that might contain
684      * <code>&lt;href&gt;</code> values to convert.
685      * @param servletContextPath The prefix which when added to a relative URI
686      * makes it an absolute one.
687      * @param config Configuration of the WebDAV servlet.
688      */

689     private static void convertHrefValueToRelativeURL (XMLValue xmlValue,
690                                                        String JavaDoc servletContextPath,
691                                                        WebdavServletConfig config) {
692         if (xmlValue != null) {
693             Iterator JavaDoc iterator = xmlValue.iterator();
694             Element element = null;
695             while (iterator.hasNext()) {
696                 Object JavaDoc o = iterator.next();
697                 if( o instanceof Element ) {
698                     element = (Element)o;
699                     convertHrefValueToRelativeURL(element, servletContextPath, config);
700                 }
701             }
702         }
703     }
704     
705     
706     
707     /**
708      * If the given <code>Element</code> contains <code>&lt;href&gt;</code>
709      * elements (at any depth), the absolute URI is converted to a relative
710      * one.
711      *
712      * This method modifies the <code>Element</code> (and its children).
713      *
714      * @param element The <code>Element</code> that might contain
715      * <code>&lt;href&gt;</code> values to convert.
716      * @param servletContextPath The prefix which when added to a relative URI
717      * makes it an absolute one.
718      * @param config Configuration of the WebDAV servlet.
719      */

720     private static void convertHrefValueToRelativeURL (Element element,
721                                                        String JavaDoc servletContextPath,
722                                                        WebdavServletConfig config) {
723         if (element.getChildren().size() > 0) {
724             Iterator JavaDoc i = element.getChildren().iterator();
725             while (i.hasNext()) {
726                 Element child = (Element) i.next();
727                 convertHrefValueToRelativeURL(child, servletContextPath, config);
728             }
729         }
730         if ( E_HREF.equals(element.getName()) && (element.getText() != null) ) {
731             if ( PropertyHelper.isAbsoluteURL(servletContextPath, element.getText()) ) {
732                 element.setText(element.getText().substring(servletContextPath.length()));
733             }
734         }
735     }
736     
737     
738     
739     /**
740      * An extension of the RequestedProperties class manages PropPatchProperty
741      * instead of RequestedProperty.
742      */

743     public class PropPatchProperties extends RequestedPropertiesImpl {
744         
745         /**
746          * Default constructor.
747          */

748         public PropPatchProperties() {
749             super();
750         }
751         
752         /**
753          * Constructs a List of PropPatchProperty from a &lt;DAV:prop&gt; element.
754          *
755          * @param propElement the &lt;DAV:prop&gt; from which to create the
756          * List of PropPatchProperty.
757          *
758          * @throws PropertyParseException if parsing the property fails for any reason.
759          */

760         public PropPatchProperties (Element propElement) throws PropertyParseException {
761             super(propElement);
762         }
763         
764         /**
765          * Creates a RequestedProperty from the given parameters. This method
766          * may be overwritten by subclasses in order to create appropriate
767          * implementations of RequestedProperty.
768          *
769          * @param name the name of the propery.
770          * @param namespacePrefix the namespace prefix of the propery.
771          * @param namespaceUri the namespace URI of the propery.
772          * @param text the text of the propery element.
773          * @param children the children of the propery element.
774          *
775          * @return the created RequestedProperty.
776          */

777         protected RequestedProperty createRequestedProperty(String JavaDoc name, String JavaDoc namespacePrefix, String JavaDoc namespaceUri, List JavaDoc content) {
778             
779             String JavaDoc value = "";
780             if (content.size() == 1 && content.get(0) instanceof Text) {
781                 value = ((Text)content.get(0)).getText();
782             }
783             else if (content.size() > 0) {
784                 XMLValue xmlVal = new XMLValue(content);
785                 if (P_GROUP_MEMBER_SET.equals(name) && S_DAV.equals(namespaceUri)) {
786                     xmlVal.stripServletContext(getSlideContextPath());
787                 }
788                 value = xmlVal.toString();
789             }
790             // register prefix/URI at NamespaceCache
791
NamespaceCache.getNamespace(namespacePrefix, namespaceUri);
792             
793             return new PropPatchProperty(name, namespaceUri, value);
794         }
795         
796     }
797     
798     /**
799      * An extension of the RequestedProperty class which supports a property value.
800      */

801     public static class PropPatchProperty extends RequestedPropertyImpl {
802         
803         /**
804          * The value of the property.
805          */

806         protected String JavaDoc value = null;
807         
808         /**
809          * The status of the PropPatch operation on this property.
810          */

811         protected int statusCode = WebdavStatus.SC_OK;
812         
813         /**
814          * The precondition that has been violated when trying to patch this
815          * property.
816          */

817         protected ViolatedPrecondition violatedPrecondition = null;
818         
819         /**
820          * If the code returned by {@link #getStatusCode getStatusCode} is not
821          * <code>200 (OK)</code> this String provides more details about the error.
822          */

823         protected String JavaDoc errorMessage = null;
824         
825         /**
826          * Provides the qualified name of the property as an Element String,
827          * i.e. if the name of the property is <code>munster</code> with
828          * the namespace <code>DAV:</code> this String is
829          * <code>&lt;munster xmlns="DAV:" /&gt;</code>.
830          */

831         protected String JavaDoc qualifiedNameAsElement = null;
832         
833         
834         /**
835          * Constructs a PropPatchProperty using the default namespace as defined
836          * in NodeProperty.
837          *
838          * @param propertyName the name of the property.
839          */

840         public PropPatchProperty (String JavaDoc propertyName) {
841             super(propertyName);
842         }
843         
844         /**
845          * Constructs a PropPatchProperty.
846          *
847          * @param propertyName the name of the property.
848          * @param namespace the namespace of the property.
849          */

850         public PropPatchProperty (String JavaDoc propertyName, String JavaDoc namespace) {
851             super(propertyName, namespace);
852         }
853         
854         /**
855          * Constructs a PropPatchProperty.
856          *
857          * @param propertyName the name of the property.
858          * @param namespace the namespace of the property.
859          * @param value the value of the property.
860          */

861         public PropPatchProperty (String JavaDoc propertyName, String JavaDoc namespace, String JavaDoc value) {
862             super(propertyName, namespace);
863             this.value = value;
864         }
865         
866         /**
867          * Returns the value of the property.
868          *
869          * @return the value of the property.
870          */

871         public String JavaDoc getValue() {
872             return value;
873         }
874         
875         /**
876          * Sets the status of the PropPatch operation on this property.
877          *
878          * @param statusCode the status code of the PropPatch operation
879          * on this property.
880          */

881         public void setStatusCode(int statusCode) {
882             this.statusCode = statusCode;
883         }
884         
885         /**
886          * Returns the status of the PropPatch operation on this property.
887          *
888          * @return the status of the PropPatch operation on this property.
889          */

890         public int getStatusCode() {
891             return statusCode;
892         }
893         
894         /**
895          * Sets the error message of this property.
896          *
897          * @param errorMessage the error message.
898          *
899          * @see #getErrorMessage
900          */

901         public void setErrorMessage(String JavaDoc errorMessage) {
902             this.errorMessage = errorMessage;
903         }
904         
905         /**
906          * If the code returned by {@link #getStatusCode getStatusCode} is not
907          * <code>200 (OK)</code> this String provides more details about the error.
908          *
909          * @return the error message.
910          */

911         public String JavaDoc getErrorMessage() {
912             return errorMessage;
913         }
914         
915         /**
916          * Sets the precondition that has been violated when trying to patch this
917          * property. If the <code>violatedPrecondition</code> is not <code>null</code>
918          * the status will be set to those of the ViolatedPrecondition.
919          *
920          * @param violatedPrecondition the precondition that has been violated
921          * when trying to patch this property.
922          */

923         public void setViolatedPrecondition(ViolatedPrecondition violatedPrecondition) {
924             this.violatedPrecondition = violatedPrecondition;
925             if (violatedPrecondition != null) {
926                 setStatusCode(violatedPrecondition.getStatusCode());
927             }
928         }
929         
930         /**
931          * Returns the precondition that has been violated when trying to patch
932          * this property.
933          *
934          * @return the precondition that has been violated when trying to
935          * patch this property.
936          */

937         public ViolatedPrecondition getViolatedPrecondition() {
938             return violatedPrecondition;
939         }
940         
941         /**
942          * Provides the qualified name of the property as an Element String,
943          * i.e. if the name of the property is <code>munster</code> with
944          * the namespace <code>DAV:</code> this method returns
945          * <code>&lt;munster xmlns="DAV:" /&gt;</code>.
946          *
947          * @return the qualified name of the property as an Element String
948          */

949         public String JavaDoc getQualifiedNameAsElementString() {
950             if (qualifiedNameAsElement == null) {
951                 StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
952                 buffer.append("<");
953                 buffer.append(getName());
954                 if ( (getNamespace() != null) && (getNamespace().length() > 0) ) {
955                     buffer.append(" xmlns=\"");
956                     buffer.append(getNamespace());
957                     buffer.append("\"");
958                     buffer.append(" />");
959                 }
960                 qualifiedNameAsElement = buffer.toString();
961             }
962             return qualifiedNameAsElement;
963         }
964         
965         /**
966          * Returns a String representation of this instance.
967          *
968          * @return a String representation of this instance.
969          */

970         public String JavaDoc toString() {
971             return getNamespace()+":"+getName()+"["+getValue()+"]";
972         }
973     }
974     
975 }
976
977
Popular Tags