You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by ju...@apache.org on 2003/05/26 11:27:53 UTC
cvs commit: jakarta-slide/src/webdav/server/org/apache/slide/webdav/method RebindMethod.java
juergen 2003/05/26 02:27:53
Added: src/webdav/server/org/apache/slide/webdav/method
RebindMethod.java
Log:
gump fix (check-in file I forgot to add)
Revision Changes Path
1.1 jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/RebindMethod.java
Index: RebindMethod.java
===================================================================
/*
* $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/RebindMethod.java,v 1.1 2003/05/26 09:27:53 juergen Exp $
* $Revision: 1.1 $
* $Date: 2003/05/26 09:27:53 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Slide", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.slide.webdav.method;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.SlideException;
import org.apache.slide.common.SlideTokenWrapper;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.content.NodeProperty.NamespaceCache;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.content.NodeRevisionNumber;
import org.apache.slide.content.RevisionDescriptorNotFoundException;
import org.apache.slide.content.RevisionNotFoundException;
import org.apache.slide.macro.CopyListener;
import org.apache.slide.macro.DeleteListener;
import org.apache.slide.macro.Macro;
import org.apache.slide.macro.MacroException;
import org.apache.slide.macro.MacroParameters;
import org.apache.slide.search.RequestedResource;
import org.apache.slide.search.Search;
import org.apache.slide.search.SearchQuery;
import org.apache.slide.search.SearchQueryResult;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.util.Configuration;
import org.apache.slide.webdav.WebdavException;
import org.apache.slide.webdav.WebdavServletConfig;
import org.apache.slide.webdav.util.DaslConstants;
import org.apache.slide.webdav.util.DeltavConstants;
import org.apache.slide.webdav.util.PreconditionViolationException;
import org.apache.slide.webdav.util.PropertyHelper;
import org.apache.slide.webdav.util.UriHandler;
import org.apache.slide.webdav.util.VersioningHelper;
import org.apache.slide.webdav.util.ViolatedPrecondition;
import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind;
import org.apache.slide.webdav.util.resourcekind.CheckedOutVersionControlled;
import org.apache.slide.webdav.util.resourcekind.DeltavCompliantUnmappedUrl;
import org.apache.slide.webdav.util.resourcekind.ResourceKind;
import org.apache.slide.webdav.util.resourcekind.VersionControlled;
import org.apache.slide.webdav.util.resourcekind.Working;
import org.apache.util.WebdavStatus;
import org.jdom.Element;
import org.jdom.JDOMException;
/**
* MOVE Method.
*
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
* @author Juergen Pill
*/
public class RebindMethod extends AbstractWebdavMethod implements DeltavConstants, DeleteListener, CopyListener {
protected String collectionUri;
protected String sourceUri;
protected String segment;
/**
* Overwrite.
*/
protected boolean overwrite;
/**
* The VersioningHelper used by this instance.
*/
protected VersioningHelper versioningHelper = null;
/**
* The PropertyHelper used by this instance.
*/
protected PropertyHelper propertyHelper = null;
/**
* Indicates if the source of the MOVE request is a workspace.
*/
protected boolean isRequestSourceWorkspace = false;
/**
* Indicates if the source of the current copy operation is a VCR.
* Used by {@link #beforeCopy beforeCopy()} and {@link #afterCopy afterCopy()}.
*/
protected boolean isCopySourceVCR = false;
/**
* The Element returned by {@link #getWorkingResourceSearchElement
* getWorkingResourceSearchElement()}.
*/
protected Element basicSearch = null;
/**
* The <literal> Element used in the basic search query returned by
* {@link #getWorkingResourceSearchElement getWorkingResourceSearchElement()}.
*/
protected Element literal = null;
// ----------------------------------------------------------- Constructors
/**
* Constructor.
*
* @param token the token for accessing the namespace
* @param config configuration of the WebDAV servlet
*/
public RebindMethod(NamespaceAccessToken token, WebdavServletConfig config) {
super(token, config);
}
// ------------------------------------------------------ Protected Methods
/**
* Parse request.
*
* @exception WebdavException Does not happen
*/
protected void parseRequest() throws WebdavException {
List content;
readRequestContent();
try {
content = parseRequestContent(E_REBIND).getChildren();
segment = MethodUtil.getChildText(content, E_SEGMENT);
sourceUri = parseUri(MethodUtil.getChildUrl(content, E_HREF));
}
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 );
}
collectionUri = requestUri;
if (collectionUri == null) {
collectionUri = "/";
} else if (!collectionUri.endsWith("/")) {
collectionUri = collectionUri + "/";
}
overwrite = MethodUtil.getOverwriteHeader(req);
checkPreconditions();
}
private void checkPreconditions() throws PreconditionViolationException {
// TODO
}
/**
* Returns true
*/
protected boolean methodNeedsTransactionSupport() {
return true;
}
private String getDestinationUri() {
return collectionUri + segment;
}
/**
* Execute request.
*
* @exception WebdavException Unrecoverable error while moving the files
*/
protected void executeRequest()
throws WebdavException, IOException {
versioningHelper = VersioningHelper.getVersioningHelper(slideToken,
token,
req,
resp,
config);
propertyHelper = PropertyHelper.getPropertyHelper(slideToken, token, getConfig());
// Prevent dirty reads
slideToken.setForceStoreEnlistment(true);
MacroParameters macroParameters = null;
boolean isCollection = isCollection(sourceUri);
String destinationUri = getDestinationUri();
if (overwrite) {
macroParameters = Macro.RECURSIVE_OVERWRITE_PARAMETERS;
} else {
macroParameters = Macro.DEFAULT_PARAMETERS;
}
// check destination URI
UriHandler destinationUriHandler = UriHandler.getUriHandler(destinationUri);
if (destinationUriHandler.isRestrictedUri()) {
int statusCode = WebdavStatus.SC_FORBIDDEN;
sendError( statusCode, getClass().getName()+".restrictedDestinationUri", new Object[]{destinationUri} );
throw new WebdavException( statusCode );
}
UriHandler sourceUriHandler = UriHandler.getUriHandler(sourceUri);
isRequestSourceWorkspace = sourceUriHandler.isWorkspaceUri();
try {
// check preconditions
ViolatedPrecondition violatedPrecondition = getPreconditionViolation(sourceUri, destinationUri);
if (violatedPrecondition != null) {
throw new PreconditionViolationException(violatedPrecondition, sourceUri);
}
macro.move(slideToken, sourceUri, destinationUri, macroParameters, null, this, null, this);
if (overwrite) {
resp.setStatus(WebdavStatus.SC_OK);
} else {
resp.setStatus(WebdavStatus.SC_CREATED);
}
} catch (MacroException e) {
// Returning 207 on non-collection requests is generally
// considered bad. So let's not do it, since this way
// makes clients generally behave better.
SlideException exception = (SlideException)e.enumerateExceptions().nextElement();
if (exception instanceof PreconditionViolationException) {
try {
sendPreconditionViolation((PreconditionViolationException)exception);
} catch(IOException ex) {
// Critical error ... Servlet container is dead or something
int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
sendError( statusCode, e );
throw new WebdavException( statusCode );
}
}
else {
int statusCode = getErrorCode( exception );
sendError( statusCode, exception );
throw new WebdavException( statusCode );
}
//
// make sure the transaction is aborted
// throw any WebDAV exception to indicate the transaction wants to be aborted
//
throw new WebdavException(WebdavStatus.SC_ACCEPTED, false);
}
catch (SlideException e) {
int statusCode = getErrorCode( e );
sendError( statusCode, e );
throw new WebdavException( statusCode );
}
}
/**
* Get return status based on exception type.
*/
protected int getErrorCode(SlideException ex) {
try {
throw ex;
} catch(RevisionNotFoundException e) {
return WebdavStatus.SC_NOT_FOUND;
} catch (SlideException e) {
return super.getErrorCode(e);
}
}
/**
* Checks the (DeltaV) preconditions
* <ul>
* <li><DAV:resource-must-be-null></li>
* <li><DAV:workspace-location-ok></li>
* </ul>
*
* @param sourceUri the URI of the resource.
* @param destinationUri the URI of the resource.
*
* @return the precondition that has been violated (if any).
*
* @throws SlideException
*/
private ViolatedPrecondition getPreconditionViolation(String sourceUri, String destinationUri) throws SlideException {
ViolatedPrecondition violatedPrecondition = null;
if( Configuration.useVersionControl() ) {
if (isRequestSourceWorkspace) {
UriHandler destinationUriHandler = UriHandler.getUriHandler(destinationUri);
NodeRevisionDescriptors destinationRevisionDescriptors = null;
NodeRevisionDescriptor destinationRevisionDescriptor = null;
try {
destinationRevisionDescriptors = content.retrieve( slideToken, destinationUri);
destinationRevisionDescriptor = content.retrieve( slideToken, destinationRevisionDescriptors);
}
catch( ObjectNotFoundException e ) {}; // can be ignored here!
ResourceKind destinationResourceKind =
AbstractResourceKind.determineResourceKind( token, destinationUri, destinationRevisionDescriptor );
if( !(destinationResourceKind instanceof DeltavCompliantUnmappedUrl) ) {
return new ViolatedPrecondition(C_RESOURCE_MUST_BE_NULL,
WebdavStatus.SC_CONFLICT);
}
if( !destinationUriHandler.isWorkspaceUri() ) {
return new ViolatedPrecondition(C_WORKSPACE_LOCATION_OK,
WebdavStatus.SC_CONFLICT);
}
}
}
return violatedPrecondition;
}
// ------------------------------------------------------ Interface CopyListener
/**
* This method is called prior to copying the resource associated by
* the given <code>sourceUri</code>. The copy can be prohibited by
* throwing a SlideException.
*
* @param sourceUri the Uri of the resource that will be copied.
* @param destinationUri the Uri of the copy.
*
* @throws SlideException this Exception will be passed to the caller
* of the Macro helper (contained in the
* MacroDeleteException.
*/
public void beforeCopy(String sourceUri, String destinationUri) throws SlideException {
if( Configuration.useVersionControl() ) {
UriHandler uriHandler = UriHandler.getUriHandler(sourceUri);
if (uriHandler.isVersionUri()) {
throw new PreconditionViolationException(new ViolatedPrecondition(DeltavConstants.C_CANNOT_RENAME_VERSION,
WebdavStatus.SC_FORBIDDEN),
sourceUri);
}
if (uriHandler.isHistoryUri()) {
throw new PreconditionViolationException(new ViolatedPrecondition(DeltavConstants.C_CANNOT_RENAME_HISTORY,
WebdavStatus.SC_FORBIDDEN),
sourceUri);
}
if (uriHandler.isWorkingresourceUri()) {
throw new PreconditionViolationException(new ViolatedPrecondition(DeltavConstants.C_CANNOT_RENAME_WORKING_RESOURCE,
WebdavStatus.SC_FORBIDDEN),
sourceUri);
}
NodeRevisionDescriptors sourceRevisionDescriptors =
content.retrieve( slideToken, sourceUri);
NodeRevisionDescriptor sourceRevisionDescriptor =
content.retrieve( slideToken, sourceRevisionDescriptors);
ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(token,
sourceRevisionDescriptors,
sourceRevisionDescriptor);
isCopySourceVCR = (resourceKind instanceof VersionControlled);
// if resource being moved is a checked-out VCR or a WR,
// update its URI in the DAV:checkout-set property of the VR
if(resourceKind instanceof CheckedOutVersionControlled || resourceKind instanceof Working) {
String vrUri =
VersioningHelper.getUriOfAssociatedVR(token, slideToken, content, sourceUri);
NodeRevisionDescriptors vrNrds = content.retrieve(slideToken, vrUri);
NodeRevisionDescriptor vrNrd = content.retrieve(slideToken, vrNrds);
try {
PropertyHelper.removeHrefFromProperty(vrNrd, P_CHECKOUT_SET, sourceUri);
PropertyHelper.addHrefToProperty(vrNrd, P_CHECKOUT_SET, destinationUri);
content.store(slideToken, vrNrds.getUri(), vrNrd, null);
}
catch (JDOMException e) {
throw new SlideException(
"Unable to update DAV:checkout-set of "+vrUri+": "+e.getMessage() );
}
}
}
}
/**
* This method is called after copying the resource to
* the given <code>destinationUri</code>.
*
* @param sourceUri the Uri of the resource that has been copied.
* @param destinationUri the Uri of the copy.
*
* @throws SlideException this Exception will be passed to the caller
* of the Macro helper (contained in the
* MacroDeleteException.
*/
public void afterCopy(String sourceUri, String destinationUri) throws SlideException {
if( Configuration.useVersionControl() ) {
NodeRevisionDescriptors sourceNrds =
content.retrieve( slideToken, sourceUri);
NodeRevisionDescriptors destinationNrds =
content.retrieve( slideToken, destinationUri);
NodeRevisionDescriptor destinationNrd =
content.retrieve( slideToken, destinationNrds );
// copy DeltaV-specific "0.0" revision if exists
try {
NodeRevisionDescriptor sourceNrd00 =
content.retrieve( slideToken, sourceNrds, NodeRevisionNumber.HIDDEN_0_0 );
NodeRevisionDescriptor destinationNrd00 = sourceNrd00.cloneObject();
try {
content.retrieve( slideToken, destinationNrds, NodeRevisionNumber.HIDDEN_0_0 );
content.store( slideToken, destinationUri, destinationNrd00, null ); // revisionContent=null
}
catch( RevisionDescriptorNotFoundException x ) {
content.create( slideToken, destinationUri, null, destinationNrd00, null ); // branch=null, revisionContent=null
}
}
catch (ServiceAccessException e) {
throw e;
}
catch (SlideException e) {}
handleWorkspacePostconditions(destinationNrd, destinationUri);
handleWorkingResourcePostconditions(sourceUri, destinationUri);
}
}
/**
* Handles the working resource postconditions.
* <ul>
* <li>DAV:update-auto-update</li>
* </ul>
*
* @param sourceUri the Uri of the resource that has been copied.
* @param destinationUri the Uri of the copy.
*
* @throws SlideException
*/
private void handleWorkingResourcePostconditions(String sourceUri, String destinationUri) throws SlideException {
if (isCopySourceVCR) {
Element basicSearch = getWorkingResourceSearchElement(sourceUri);
String grammarNamespace = basicSearch.getNamespaceURI();
Search searchHelper = token.getSearchHelper();
StringBuffer requestURIWithScope = new StringBuffer(req.getContextPath());
requestURIWithScope.append(sourceUri);
SearchQuery searchQuery = searchHelper.createSearchQuery(grammarNamespace,
basicSearch,
new SlideTokenWrapper(slideToken, false),
Integer.MAX_VALUE,
requestURIWithScope.toString());
SearchQueryResult queryResult = searchHelper.search(new SlideTokenWrapper(slideToken, false), searchQuery);
Iterator queryResultIterator = queryResult.iterator();
RequestedResource requestedResource = null;
NodeRevisionDescriptors workingResourceRevisionDescriptors = null;
NodeRevisionDescriptor workingResourceRevisionDescriptor = null;
NodeProperty autoUpdateProperty = null;
String workingResourceUri = null;
while (queryResultIterator.hasNext()) {
requestedResource = (RequestedResource)queryResultIterator.next();
workingResourceUri = requestedResource.getUri();
workingResourceRevisionDescriptors =
content.retrieve( slideToken, workingResourceUri);
workingResourceRevisionDescriptor =
content.retrieve( slideToken, workingResourceRevisionDescriptors);
autoUpdateProperty = new NodeProperty(P_AUTO_UPDATE,
propertyHelper.createHrefValue(destinationUri));
workingResourceRevisionDescriptor.setProperty(autoUpdateProperty);
content.store(slideToken,
workingResourceRevisionDescriptors.getUri(),
workingResourceRevisionDescriptor,
null);
}
}
}
/**
* Returns the query document used to search all resources that have
* a <auto-update> property with a <href> value containing
* the given <code>resourcePath</code>.
*
* @param resourcePath the Uri to search for.
*
* @return the query document.
*/
protected Element getWorkingResourceSearchElement(String resourcePath) {
if (basicSearch == null) {
basicSearch = new Element(DaslConstants.E_BASICSEARCH,
NamespaceCache.DEFAULT_NAMESPACE);
Element select = new Element(DaslConstants.E_SELECT,
NamespaceCache.DEFAULT_NAMESPACE);
basicSearch.addContent(select);
Element prop = new Element(E_PROP,
NamespaceCache.DEFAULT_NAMESPACE);
select.addContent(prop);
Element autoUpdate = new Element(P_AUTO_UPDATE,
NamespaceCache.DEFAULT_NAMESPACE);
prop.addContent(autoUpdate);
Element from = new Element(DaslConstants.E_FROM,
NamespaceCache.DEFAULT_NAMESPACE);
basicSearch.addContent(from);
Element scope = new Element(DaslConstants.E_SCOPE,
NamespaceCache.DEFAULT_NAMESPACE);
from.addContent(scope);
Element href = new Element(E_HREF,
NamespaceCache.DEFAULT_NAMESPACE);
scope.addContent(href);
href.setText("");
Iterator excludeIterator = propertyHelper.getNonVcrPathExcludeList().iterator();
while (excludeIterator.hasNext()) {
scope.addContent((Element)excludeIterator.next());
}
Element where = new Element(DaslConstants.E_WHERE,
NamespaceCache.DEFAULT_NAMESPACE);
basicSearch.addContent(where);
Element propcontains = new Element(DaslConstants.E_PROPCONTAINS,
NamespaceCache.SLIDE_NAMESPACE);
where.addContent(propcontains);
propcontains.addContent((Element)prop.clone());
literal = new Element(DaslConstants.E_LITERAL,
NamespaceCache.DEFAULT_NAMESPACE);
propcontains.addContent(literal);
}
literal.setText(resourcePath);
return basicSearch;
}
/**
* Handles the workspace postconditions
* <ul>
* <li>DAV:workspace-moved</li>
* <li>DAV:workspace-member-moved</li>
* </ul>
*
* @param revisionDescriptor the NodeRevisionDescriptor of the resource.
* @param resourceUri the URI of the resource.
*
* @throws SlideException
*/
protected void handleWorkspacePostconditions(NodeRevisionDescriptor revisionDescriptor, String resourceUri) throws SlideException {
if( Configuration.useVersionControl() ) {
if (isRequestSourceWorkspace) {
// DAV:workspace-moved
revisionDescriptor.setProperty(
new NodeProperty( P_WORKSPACE, propertyHelper.createHrefValue(getDestinationUri())) );
}
else {
// DAV:workspace-member-moved
versioningHelper.setWorkspaceProperty(resourceUri, revisionDescriptor);
}
content.store(slideToken, resourceUri, revisionDescriptor, null);
}
}
// ------------------------------------------------------ Interface DeleteListener
/**
* This method is called prior to deleting the resource associated by
* the given <code>targetUri</code>. The deletion can be prohibited by
* throwing a SlideException.
*
* @param targetUri the Uri of the resource that will be deleted.
*
* @throws SlideException this Exception will be passed to the caller
* of the Macro helper (contained in the
* MacroDeleteException.
*/
public void beforeDelete(String targetUri) throws SlideException {
}
/**
* This method is called after deleting the resource associated by
* the given <code>targetUri</code>.
*
* @param targetUri the Uri of the resource that will be deleted.
*
* @throws SlideException this Exception will be passed to the caller
* of the Macro helper (contained in the
* MacroDeleteException.
*/
public void afterDelete(String targetUri) throws SlideException {
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org