1 23 24 package org.apache.slide.webdav.method; 25 26 import java.io.IOException; 27 import java.util.Enumeration; 28 import java.util.Iterator; 29 import java.util.List; 30 import java.util.Stack; 31 32 import org.apache.slide.common.NamespaceAccessToken; 33 import org.apache.slide.common.PropertyParseException; 34 import org.apache.slide.common.RequestedProperties; 35 import org.apache.slide.common.RequestedPropertiesImpl; 36 import org.apache.slide.common.RequestedProperty; 37 import org.apache.slide.common.ServiceAccessException; 38 import org.apache.slide.common.SlideException; 39 import org.apache.slide.common.SlideToken; 40 import org.apache.slide.common.SlideTokenWrapper; 41 import org.apache.slide.common.UriPath; 42 import org.apache.slide.content.NodeRevisionDescriptor; 43 import org.apache.slide.content.NodeRevisionDescriptors; 44 import org.apache.slide.content.RevisionDescriptorNotFoundException; 45 import org.apache.slide.event.EventDispatcher; 46 import org.apache.slide.security.AccessDeniedException; 47 import org.apache.slide.structure.ObjectNode; 48 import org.apache.slide.structure.StructureException; 49 import org.apache.slide.util.Configuration; 50 import org.apache.slide.webdav.WebdavException; 51 import org.apache.slide.webdav.WebdavServletConfig; 52 import org.apache.slide.webdav.event.WebdavEvent; 53 import org.apache.slide.webdav.util.AclConstants; 54 import org.apache.slide.webdav.util.DeltavConstants; 55 import org.apache.slide.webdav.util.LabeledRevisionNotFoundException; 56 import org.apache.slide.webdav.util.PropertyRetrieverImpl; 57 import org.apache.slide.webdav.util.UnlockListenerImpl; 58 import org.apache.slide.webdav.util.VersioningHelper; 59 import org.apache.slide.webdav.util.WebdavStatus; 60 import org.apache.slide.webdav.util.WebdavUtils; 61 import org.jdom.Document; 62 import org.jdom.Element; 63 import org.jdom.JDOMException; 64 import org.jdom.Namespace; 65 import org.jdom.input.SAXBuilder; 66 import org.jdom.output.XMLOutputter; 67 68 72 public class PropFindMethod extends AbstractWebdavMethod implements DeltavConstants, AclConstants, ReadMethod { 73 74 77 protected static final int FIND_BY_PROPERTY = 0; 78 79 80 83 protected static final int FIND_ALL_PROP = 1; 84 85 86 89 protected static final int FIND_PROPERTY_NAMES = 2; 90 91 93 94 97 protected int depth; 98 99 100 103 protected int propFindType; 104 105 106 protected boolean extendedAllprop = false; 107 108 109 110 113 protected static SAXBuilder saxBuilder = null; 114 115 118 protected RequestedProperties requestedProperties = null; 119 120 121 124 protected String resourcePath; 125 126 129 protected VersioningHelper versioningHelper = null; 130 131 134 protected String labelHeader = null; 135 136 141 protected boolean outputOptimized = true; 142 143 145 146 152 public PropFindMethod(NamespaceAccessToken token, 153 WebdavServletConfig config) { 154 super(token, config); 155 } 156 157 158 160 161 166 protected void parseRequest() throws WebdavException { 167 168 versioningHelper = VersioningHelper.getVersioningHelper( 169 slideToken, token, req, resp, getConfig() ); 170 172 depth = INFINITY; 173 propFindType = FIND_ALL_PROP; 174 extendedAllprop = getBooleanInitParameter( "extendedAllprop" ); 175 outputOptimized = getBooleanInitParameter( "optimizePropfindOutput" ); 176 177 resourcePath = requestUri; 178 if (resourcePath == null) { 179 resourcePath = "/"; 180 } 181 182 labelHeader = WebdavUtils.fixTomcatHeader(requestHeaders.getLabel(), "UTF-8"); 183 184 retrieveDepth(); 185 186 if (req.getContentLength() == 0) { 187 requestedProperties = new RequestedPropertiesImpl(); 188 requestedProperties.setIsAllProp(true); 189 propFindType = FIND_ALL_PROP; 190 } 191 else { 192 193 try { 194 195 Element element = parseRequestContent(E_PROPFIND); 196 try { 197 element = (Element)element.getChildren().get(0); 198 } 199 catch (Exception e) { 200 int statusCode = WebdavStatus.SC_BAD_REQUEST; 201 sendError( statusCode, getClass().getName()+".missingRootElementChildren", new Object[]{"DAV:"+E_PROPFIND} ); 202 throw new WebdavException( statusCode ); 203 } 204 205 if (element.getName().equalsIgnoreCase(E_PROPNAME)){ 206 propFindType = FIND_PROPERTY_NAMES; 207 } 208 else if ( element.getName().equalsIgnoreCase(E_PROP) ) { 209 requestedProperties = new RequestedPropertiesImpl(element); 210 propFindType = FIND_BY_PROPERTY; 211 } 212 else if ( element.getName().equalsIgnoreCase(E_ALLPROP) ) { 213 requestedProperties = new RequestedPropertiesImpl(element); 214 propFindType = FIND_ALL_PROP; 215 } 216 else { 217 int statusCode = WebdavStatus.SC_BAD_REQUEST; 218 sendError( statusCode, getClass().getName()+".invalidChildOfRootElement", new Object[]{element.getNamespace()+":"+element.getName(),"DAV:"+E_PROPFIND} ); 219 throw new WebdavException( statusCode ); 220 } 221 222 } 223 catch (JDOMException e){ 224 int statusCode = WebdavStatus.SC_BAD_REQUEST; 225 sendError( statusCode, e ); 226 throw new WebdavException( statusCode ); 227 } 228 catch (PropertyParseException e){ 229 int statusCode = WebdavStatus.SC_BAD_REQUEST; 230 sendError( statusCode, e ); 231 throw new WebdavException( statusCode ); 232 } 233 catch (IOException e){ 234 int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR; 235 sendError( statusCode, e ); 236 throw new WebdavException( statusCode ); 237 } 238 } 239 } 240 241 244 private void retrieveDepth() throws WebdavException { 245 depth = requestHeaders.getDepth(INFINITY); 246 247 if (depth > getConfig().getDepthLimit()) { 249 depth = getConfig().getDepthLimit(); 250 } 251 } 252 253 254 255 260 protected void executeRequest() throws IOException, WebdavException { 261 262 resp.setStatus(WebdavStatus.SC_MULTI_STATUS); 263 264 266 ObjectNode resource = null; 268 269 try { 270 if ( WebdavEvent.PROPFIND.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(WebdavEvent.PROPFIND, new WebdavEvent(this)); 271 resource = structure.retrieve(slideToken, resourcePath); 272 } catch (StructureException e) { 273 int statusCode = WebdavStatus.SC_NOT_FOUND; 274 sendError( statusCode, e ); 275 throw new WebdavException( statusCode ); 276 } catch (Exception e) { 277 int statusCode = getErrorCode( e ); 278 sendError( statusCode, e ); 279 throw new WebdavException( statusCode ); 280 } 281 282 resp.setContentType(TEXT_XML_UTF_8); 283 284 Element multistatusElement = new Element(E_MULTISTATUS, DNSP); 286 org.jdom.output.Format format = org.jdom.output.Format.getPrettyFormat(); 287 format.setIndent(XML_RESPONSE_INDENT); 288 XMLOutputter xmlOutputter = new XMLOutputter(format); 289 290 if (resource != null) { 291 if (depth == 0) { 292 multistatusElement.addContent(getPropertiesOfObject(resource.getUri())); 293 xmlOutputter.output(new Document(multistatusElement), resp.getWriter()); 294 } else { 295 Stack stack = new Stack(); 297 stack.push(resource); 298 299 Stack stackBelow = new Stack(); 301 302 StringBuffer buffer = new StringBuffer(); 303 if (outputOptimized) { 304 305 resp.getWriter().write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); 306 resp.getWriter().write("\n"); 307 String namespacePrefix = multistatusElement.getNamespacePrefix(); 308 if ( (namespacePrefix != null) && (namespacePrefix.length() == 0) ) { 309 namespacePrefix = null; 310 } 311 String namespaceUri = multistatusElement.getNamespaceURI(); 312 if ( (namespaceUri != null) && (namespaceUri.length() == 0) ) { 313 namespaceUri = null; 314 } 315 buffer.append("<"); 316 buffer.append(multistatusElement.getQualifiedName()); 317 if (namespaceUri != null) { 318 buffer.append(" xmlns"); 319 if (namespacePrefix != null) { 320 buffer.append(":"); 321 buffer.append(namespacePrefix); 322 } 323 buffer.append("=\""); 324 buffer.append(namespaceUri); 325 buffer.append("\""); 326 } 327 buffer.append(">"); 328 resp.getWriter().write(buffer.toString()); 329 resp.getWriter().write("\n"); 330 } 331 332 while ((!stack.isEmpty()) && (depth >= 0)) { 333 334 ObjectNode cur = (ObjectNode) stack.pop(); 335 Element response = getPropertiesOfObject(cur.getUri()); 336 if (outputOptimized) { 337 xmlOutputter.output(response, resp.getWriter()); 338 } 339 else { 340 multistatusElement.addContent(response); 341 } 342 343 if (depth > 0) { 344 345 Enumeration enum = null; 346 347 try { 348 enum = structure.getChildren(slideToken, cur); 349 } catch (Exception e) { 350 int statusCode = getErrorCode( e ); 351 sendError( statusCode, e ); 352 throw new WebdavException( statusCode ); 353 } 354 355 while (enum.hasMoreElements()) { 356 ObjectNode node = (ObjectNode)enum.nextElement(); 359 UnlockListenerImpl listener = new UnlockListenerImpl( 360 slideToken, token, config, req, resp); 361 try { 362 lock.clearExpiredLocks(slideToken, node.getUri(), listener); 363 if (!listener.isRemovedLockResource(node.getUri())) { 364 stackBelow.push(node); 365 } 366 } catch (SlideException e) { } 367 } 368 369 } 370 371 if (stack.isEmpty()) { 372 depth--; 373 stack = stackBelow; 374 stackBelow = new Stack(); 375 } 376 377 } 378 379 if (outputOptimized) { 380 resp.getWriter().write("\n"); 381 buffer.setLength(0); 382 buffer.append("</"); 383 buffer.append(multistatusElement.getQualifiedName()); 384 buffer.append(">"); 385 resp.getWriter().write(buffer.toString()); 386 resp.getWriter().write("\n"); 387 } 388 else { 389 xmlOutputter.output(new Document(multistatusElement), resp.getWriter()); 390 } 391 } 392 } 393 394 } 395 396 397 406 protected Element getPropertiesOfObject(String resourceUri) 407 throws WebdavException { 408 409 SlideToken lightSToken = new SlideTokenWrapper(slideToken); 410 lightSToken.setForceLock(false); 411 412 if (Configuration.useVersionControl()) { 414 try { 415 resourceUri = versioningHelper.getLabeledResourceUri(resourceUri, labelHeader); 416 } 417 catch (LabeledRevisionNotFoundException e) { 418 return getErrorResponse(resourceUri, 419 WebdavStatus.SC_CONFLICT, 420 DeltavConstants.C_MUST_SELECT_VERSION_IN_HISTORY); 421 } 422 catch( RevisionDescriptorNotFoundException x ) { 423 } 424 catch (SlideException e) { 425 return getErrorResponse(resourceUri, getErrorCode(e), null); 426 } 427 } 428 429 ObjectNode object = null; 430 try { 431 object = structure.retrieve(lightSToken, resourceUri); 432 } 433 catch (SlideException e) { 434 return getErrorResponse(resourceUri, getErrorCode(e), null); 435 } 436 437 Element responseElement = new Element(E_RESPONSE, DNSP); 438 439 String status = new String(HTTP_VERSION + WebdavStatus.SC_OK + " " 440 + WebdavStatus.getStatusText 441 (WebdavStatus.SC_OK)); 442 NodeRevisionDescriptors revisionDescriptors = null; 443 NodeRevisionDescriptor revisionDescriptor = null; 444 445 447 449 try { 450 Element hrefElement = new Element(E_HREF, DNSP); 451 452 String resourcePath = object.getUri(); 455 456 revisionDescriptors = 457 content.retrieve(lightSToken, resourcePath); 458 459 try { 460 revisionDescriptor = content.retrieve(lightSToken, 461 revisionDescriptors); 462 463 465 hrefElement.setText( 466 WebdavUtils.getAbsolutePath(object.getUri(), req, 467 getConfig())); 468 469 } catch (RevisionDescriptorNotFoundException e) { 470 471 revisionDescriptor = new NodeRevisionDescriptor(0); 475 476 if (!Configuration.useBinding(token.getUri(lightSToken, object.getUri()).getStore())) { 477 revisionDescriptor.setName(new UriPath(object.getUri()).lastSegment()); 478 } 479 480 hrefElement.setText( 481 WebdavUtils.getAbsolutePath(object.getUri(), req, 482 getConfig())); 483 } 484 485 responseElement.addContent(hrefElement); 486 487 489 493 } catch (AccessDeniedException e) { 494 if (revisionDescriptor == null) { 495 revisionDescriptor = new NodeRevisionDescriptor(0); 496 } 497 } catch (Exception e) { 498 int statusCode = getErrorCode( e ); 499 sendError( statusCode, e ); 500 throw new WebdavException( statusCode ); 501 } 502 503 PropertyRetrieverImpl propertyRetriever = new PropertyRetrieverImpl(token, lightSToken, getConfig()); 504 505 switch (propFindType) { 506 case FIND_ALL_PROP : 507 case FIND_BY_PROPERTY : 508 try { 509 List propstatList= propertyRetriever.getPropertiesOfObject(requestedProperties, revisionDescriptors, revisionDescriptor, getSlideContextPath(), extendedAllprop); 510 Iterator iterator = propstatList.iterator(); 511 while (iterator.hasNext()) { 512 responseElement.addContent((Element)iterator.next()); 513 } 514 } catch (ServiceAccessException e) { 515 int statusCode = WebdavStatus.SC_FORBIDDEN; 516 sendError( statusCode, e ); 517 throw new WebdavException( statusCode ); 518 } catch (Exception e) { 519 int statusCode = getErrorCode( e ); 520 sendError( statusCode, e ); 521 throw new WebdavException( statusCode ); 522 } 523 break; 524 case FIND_PROPERTY_NAMES : 525 526 try { 527 status = new String("HTTP/1.1 " + WebdavStatus.SC_OK 528 + " " + WebdavStatus.getStatusText 529 (WebdavStatus.SC_OK)); 530 531 Element propstatElement = new Element(E_PROPSTAT, DNSP); 532 Element propElement = new Element(E_PROP, DNSP); 533 RequestedProperties propnames = 534 propertyRetriever.getAllPropertyNames(object.getUri(), true); 535 Iterator iterator = propnames.getRequestedProperties(); 536 while (iterator.hasNext()) { 537 RequestedProperty p = (RequestedProperty)iterator.next(); 538 Namespace nsp = DNSP.getURI().equals(p.getNamespace()) 539 ? DNSP 540 : Namespace.getNamespace(p.getNamespace()); 541 propElement.addContent(new Element(p.getName(), nsp)); 542 } 543 Element statusElement = new Element(E_STATUS, DNSP); 544 statusElement.setText(status); 545 propstatElement.addContent(propElement); 546 propstatElement.addContent(statusElement); 547 responseElement.addContent(propstatElement); 548 } 549 catch (ServiceAccessException e) { 550 int statusCode = WebdavStatus.SC_FORBIDDEN; 551 sendError( statusCode, e ); 552 throw new WebdavException( statusCode ); 553 } 554 catch (Exception e) { 555 int statusCode = getErrorCode( e ); 556 sendError( statusCode, e ); 557 throw new WebdavException( statusCode ); 558 } 559 break; 560 } 561 562 return responseElement; 563 } 564 565 574 private Element getErrorResponse(String resourcePath, int errorCode, String condition) { 575 576 Element response = new Element(E_RESPONSE, DNSP); 577 578 Element href = new Element(E_HREF, DNSP); 579 href.setText(HTTP_PROTOCOL + 580 req.getServerName()+ ":" + 581 req.getServerPort() + 582 getSlideContextPath() + 583 resourcePath); 584 response.addContent(href); 585 Element propStat = new Element(E_PROPSTAT, DNSP); 586 response.addContent(propStat); 587 588 Element status = new Element(E_STATUS, DNSP); 589 status.setText(HTTP_VERSION + " " + errorCode + " " + WebdavStatus.getStatusText(errorCode)); 590 propStat.addContent(status); 591 592 if (condition != null) { 593 Element responseDescriptiont = new Element(E_RESPONSEDESCRIPTION, DNSP); 594 Element errorElement = new Element(E_ERROR, DNSP); 595 responseDescriptiont.addContent(errorElement); 596 Element conditionElement = new Element(condition, DNSP); 597 errorElement.addContent(conditionElement); 598 propStat.addContent(responseDescriptiont); 599 } 600 return response; 601 } 602 } 603 604 605 606 607 608 609 610 611 612 | Popular Tags |