/*
* $Header: /home/cvspublic/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/ReportMethod.java,v 1.74 2005/02/25 17:03:53 luetzkendorf Exp $
* $Revision: 1.74 $
* $Date: 2005/02/25 17:03:53 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.slide.webdav.method;
import java.io.IOException;
import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.SlideToken;
import org.apache.slide.event.EventDispatcher;
import org.apache.slide.webdav.WebdavException;
import org.apache.slide.webdav.WebdavServletConfig;
import org.apache.slide.webdav.event.WebdavEvent;
import org.apache.slide.webdav.method.report.AbstractReport;
import org.apache.slide.webdav.method.report.AclPrincipalPropSetReport;
import org.apache.slide.webdav.method.report.ExpandPropertyReport;
import org.apache.slide.webdav.method.report.LocateByHistoryReport;
import org.apache.slide.webdav.method.report.PrincipalMatchReport;
import org.apache.slide.webdav.method.report.PrincipalPropertySearchReport;
import org.apache.slide.webdav.method.report.PrincipalSearchPropertySetReport;
import org.apache.slide.webdav.method.report.VersionTreeReport;
import org.apache.slide.webdav.util.AclConstants;
import org.apache.slide.webdav.util.DeltavConstants;
import org.apache.slide.webdav.util.PreconditionViolationException;
import org.apache.slide.webdav.util.WebdavStatus;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.output.XMLOutputter;
/**
* REPORT method.
*
*/
public class ReportMethod extends AbstractWebdavMethod implements DeltavConstants, AclConstants,
ReadMethod, FineGrainedLockingMethod {
private String resourcePath;
private AbstractReport reportWorker;
private String servletPath;
/**
* Constructor.
*
* @param token the token for accessing the namespace
* @param config configuration of the WebDAV servlet
*/
public ReportMethod(NamespaceAccessToken token, WebdavServletConfig config) {
super(token, config);
}
/**
* @see org.apache.slide.webdav.method.FineGrainedLockingMethod#acquireFineGrainLocks()
*/
public void acquireFineGrainLocks() {
acquireStandardLocks(resourcePath);
// read lock history folder
acquireHistoryLocks(resourcePath);
}
/**
* Parse WebDAV XML request body.
*
* @exception WebdavException
*/
protected void parseRequest() throws WebdavException {
Element reportElm;
String reportName;
resourcePath = requestUri;
if (resourcePath == null) {
resourcePath = "/";
}
servletPath = req.getServletPath();
try{
reportElm = parseRequestContent().getRootElement();
reportName = reportElm.getName();
reportWorker = getExternalReportWorker(reportName);
if (reportWorker == null) {
if (R_EXPAND_PROPERTY.equals(reportName)) {
reportWorker = new ExpandPropertyReport(slideToken, token, config, getSlideContextPath());
}
else if (R_VERSION_TREE.equals(reportName)) {
reportWorker = new VersionTreeReport(slideToken, token, config, getSlideContextPath());
((VersionTreeReport)reportWorker).setVersioningHelper(versioningHelper);
}
else if (R_LOCATE_BY_HISTORY.equals(reportName)) {
reportWorker = new LocateByHistoryReport(slideToken, token, config, getSlideContextPath());
}
else if (R_ACL_PRINCIPAL_PROP_SET.equals(reportName)) {
reportWorker = new AclPrincipalPropSetReport(slideToken, token, config, getSlideContextPath());
}
else if (R_PRINCIPAL_MATCH.equals(reportName)) {
reportWorker = new PrincipalMatchReport(slideToken, token, config, getSlideContextPath());
}
else if (R_PRINCIPAL_PROPERTY_SEARCH.equals(reportName)) {
reportWorker = new PrincipalPropertySearchReport(slideToken, token, config, getSlideContextPath());
}
else if (R_PRINCIPAL_SEARCH_PROPERTY_SET.equals(reportName)) {
reportWorker = new PrincipalSearchPropertySetReport(slideToken, token, config, getSlideContextPath());
}
}
if (reportWorker != null) {
reportWorker.init(resourcePath, reportElm);
}
else {
int statusCode = WebdavStatus.SC_BAD_REQUEST;
sendError( statusCode, new Exception("Unknown report "+reportName) );
throw new WebdavException( statusCode );
}
}
catch (IOException e) { // TODO: merge exception handling into jdom access methods
int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
sendError( statusCode, e );
throw new WebdavException( statusCode );
}
catch (JDOMException e) { // TODO: merge exception handling into jdom access methods
int statusCode = WebdavStatus.SC_BAD_REQUEST;
sendError( statusCode, e );
throw new WebdavException( statusCode );
}
catch (PreconditionViolationException e) { // TODO: merge exception handling into jdom access methods
try {
sendPreconditionViolation(e);
throw e;
} catch (IOException x) {}
throw new WebdavException(e.getStatusCode());
}
}
private AbstractReport getExternalReportWorker(String reportName) throws JDOMException, WebdavException {
AbstractReport result = null;
String clsName = config.getExternalReport(reportName);
if (clsName != null) {
try {
Class cls = Class.forName(clsName);
Class[] parmtypes = {SlideToken.class,
NamespaceAccessToken.class,
WebdavServletConfig.class,
String.class,
String.class
};
Object[] initargs = {slideToken,
token,
config,
servletPath,
getSlideContextPath()
};
result =
(AbstractReport)cls.getConstructor(parmtypes).newInstance(initargs);
}
catch( Exception e ) {
int statusCode = WebdavStatus.SC_BAD_REQUEST;
sendError( statusCode, new Exception("Cannot create "+reportName+" report worker "+clsName+" ["+e+"]") );
throw new WebdavException( statusCode );
}
}
return result;
}
/**
* Execute the request.
*
* @exception WebdavException
*/
protected void executeRequest() throws WebdavException, IOException {
resp.setContentType(TEXT_XML_UTF_8);
// check lock-null resources
try {
if (isLockNull(resourcePath)) {
int statusCode = WebdavStatus.SC_NOT_FOUND;
sendError( statusCode, "lock-null resource", new Object[]{resourcePath} );
throw new WebdavException( statusCode );
}
}
catch (ServiceAccessException e) {
int statusCode = getErrorCode( e );
sendError( statusCode, e );
throw new WebdavException( statusCode );
}
try {
if ( WebdavEvent.REPORT.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(WebdavEvent.REPORT, new WebdavEvent(this));
reportWorker.checkPreconditions(resourcePath, getDepth());
Element rootElm;
if (reportWorker instanceof PrincipalSearchPropertySetReport) {
rootElm = new Element(E_PRINCIPAL_SEARCH_PROPERTY_SET, DNSP);
reportWorker.execute(resourcePath, rootElm, getDepth());
resp.setStatus(WebdavStatus.SC_OK);
}
else {
rootElm = new Element(E_MULTISTATUS, DNSP);
reportWorker.execute(resourcePath, rootElm, getDepth());
resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
}
org.jdom.output.Format format = org.jdom.output.Format.getPrettyFormat();
format.setIndent(XML_RESPONSE_INDENT);
new XMLOutputter(format).
output(new Document(rootElm), resp.getWriter());
}
catch (PreconditionViolationException e) {
sendPreconditionViolation(e);
throw e;
}
catch (Exception e) {
int statusCode = getErrorCode( e );
sendError( statusCode, e );
throw new WebdavException( statusCode );
}
}
/**
* Returns the value of the Depth
request header.
*
* @return the value of the Depth
request header.
*/
private int getDepth() throws WebdavException {
int depth = requestHeaders.getDepth(0);
// limit tree browsing a bit
if (depth > config.getDepthLimit()) {
depth = config.getDepthLimit();
}
return depth;
}
}