Index: src/main/java/org/apache/jackrabbit/server/io/CopyMoveManager.java =================================================================== --- src/main/java/org/apache/jackrabbit/server/io/CopyMoveManager.java (revision ) +++ src/main/java/org/apache/jackrabbit/server/io/CopyMoveManager.java (revision ) @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.jackrabbit.server.io; + +import org.apache.jackrabbit.webdav.DavResourceLocator; + +import javax.jcr.Session; +import java.io.IOException; + +/** + * CopyMoveManager... + */ +public interface CopyMoveManager { + + /** + * Handles the copy command + * + * @param session + * @param locator + * @param dstPath + * @return + * @throws IOException + */ + public boolean copyContent(Session session, DavResourceLocator locator, String dstPath) throws IOException; + + /** + * Handles the move command + * + * @param session + * @param locator + * @param dstPath + * @return + * @throws IOException + */ + public boolean moveContent(Session session, DavResourceLocator locator, String dstPath) throws IOException; + + /** + * Adds the specified handler to the list of handlers. + * + * @param copyMoveHandler handler to be added + */ + public void addCopyMoveHandler(CopyMoveHandler copyMoveHandler); + + /** + * Returns all handlers that have been added to this manager. + * + * @return Array of all handlers + */ + public CopyMoveHandler[] getCopyMoveHandlers(); +} Index: src/main/java/org/apache/jackrabbit/server/io/CopyMoveManagerImpl.java =================================================================== --- src/main/java/org/apache/jackrabbit/server/io/CopyMoveManagerImpl.java (revision ) +++ src/main/java/org/apache/jackrabbit/server/io/CopyMoveManagerImpl.java (revision ) @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.jackrabbit.server.io; + +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Session; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * CopyMoveManagerImpl... + */ +public class CopyMoveManagerImpl implements CopyMoveManager { + + private static Logger log = LoggerFactory.getLogger(CopyMoveManagerImpl.class); + + private static CopyMoveManager DEFAULT_MANAGER; + + private final List copyMoveHandlers = new ArrayList(); + + /** + * Create a new CopyMoveManagerImpl. + */ + public CopyMoveManagerImpl() { + } + + /** + * @see org.apache.jackrabbit.server.io.CopyMoveManager#copyContent(javax.jcr.Session, org.apache.jackrabbit.webdav.DavResourceLocator, String) + */ + public boolean copyContent(Session session, DavResourceLocator locator, String dstPath) throws IOException { + boolean success = false; + CopyMoveHandler[] copyMoveHandlers = getCopyMoveHandlers(); + for (int i = 0; i < copyMoveHandlers.length && !success; i++) { + CopyMoveHandler cmh = copyMoveHandlers[i]; + if (cmh.canCopy(locator, dstPath)) { + success = cmh.copyContent(session, locator, dstPath); + } + } + return success; + } + + /** + * @see org.apache.jackrabbit.server.io.CopyMoveManager#moveContent(javax.jcr.Session, org.apache.jackrabbit.webdav.DavResourceLocator, String) + */ + public boolean moveContent(Session session, DavResourceLocator locator, String dstPath) throws IOException { + boolean success = false; + CopyMoveHandler[] copyMoveHandlers = getCopyMoveHandlers(); + for (int i = 0; i < copyMoveHandlers.length && !success; i++) { + CopyMoveHandler cmh = copyMoveHandlers[i]; + if (cmh.canMove(locator, dstPath)) { + success = cmh.moveContent(session, locator, dstPath); + } + } + return success; + } + + /** + * @see org.apache.jackrabbit.server.io.CopyMoveManager#addCopyMoveHandler(CopyMoveHandler) + */ + public void addCopyMoveHandler(CopyMoveHandler copyMoveHandler) { + if (copyMoveHandler == null) { + throw new IllegalArgumentException("'null' is not a valid copyMoveHandler."); + } + copyMoveHandlers.add(copyMoveHandler); + } + + /** + * @see CopyMoveManager#getCopyMoveHandlers() + */ + public CopyMoveHandler[] getCopyMoveHandlers() { + return copyMoveHandlers.toArray(new CopyMoveHandler[copyMoveHandlers.size()]); + } + + /** + * @return an instance of CopyMoveManager populated with default handlers. + */ + public static CopyMoveManager getDefaultManager() { + if (DEFAULT_MANAGER == null) { + DEFAULT_MANAGER = new CopyMoveManagerImpl(); + DEFAULT_MANAGER.addCopyMoveHandler(new DefaultHandler()); + } + return DEFAULT_MANAGER; + } +} Index: src/main/java/org/apache/jackrabbit/server/io/DefaultHandler.java =================================================================== --- src/main/java/org/apache/jackrabbit/server/io/DefaultHandler.java (revision 1155390) +++ src/main/java/org/apache/jackrabbit/server/io/DefaultHandler.java (revision ) @@ -20,7 +20,11 @@ import org.apache.jackrabbit.commons.NamespaceHelper; import org.apache.jackrabbit.util.ISO9075; import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; import org.apache.jackrabbit.webdav.xml.Namespace; import org.apache.jackrabbit.webdav.property.DavPropertyName; import org.apache.jackrabbit.webdav.property.DavProperty; @@ -67,7 +71,7 @@ * Subclasses therefore should provide their own {@link #importData(ImportContext, boolean, Node) * importData} method, that handles the data according their needs. */ -public class DefaultHandler implements IOHandler, PropertyHandler { +public class DefaultHandler implements IOHandler, PropertyHandler, CopyMoveHandler { private static Logger log = LoggerFactory.getLogger(DefaultHandler.class); @@ -671,6 +675,33 @@ } } + //--------------------------------------------------< CopyMoveHandler >--- + public boolean canCopy(DavResourceLocator locator, String dstPath) throws IOException { + return true; + } + + public boolean copyContent(Session session, DavResourceLocator locator, String dstPath) throws IOException { + try { + session.getWorkspace().copy(locator.getRepositoryPath(), dstPath); + return true; + } catch (RepositoryException e) { + throw new IOException(e.getMessage()); + } + } + + public boolean canMove(DavResourceLocator locator, String dstPath) throws IOException { + return true; + } + + public boolean moveContent(Session session, DavResourceLocator locator, String dstPath) throws IOException { + try { + session.getWorkspace().move(locator.getRepositoryPath(), dstPath); + return true; + } catch (RepositoryException e) { + throw new IOException(e.getMessage()); + } + } + //------------------------------------------------------------< private >--- /** * Builds a webdav property name from the given jcrName. In case the jcrName Index: src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java =================================================================== --- src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (revision 1155286) +++ src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (revision ) @@ -68,7 +68,6 @@ import javax.jcr.Item; import javax.jcr.Node; import javax.jcr.NodeIterator; -import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.Workspace; @@ -599,13 +598,17 @@ } // make sure, that src and destination belong to the same workspace checkSameWorkspace(destination.getLocator()); - try { - String destItemPath = destination.getLocator().getRepositoryPath(); + String destItemPath = destination.getLocator().getRepositoryPath(); - getJcrSession().getWorkspace().move(locator.getRepositoryPath(), destItemPath); - } catch (RepositoryException e) { - throw new JcrDavException(e); + try { + if (!config.getCopyMoveManager().moveContent(getJcrSession(), locator, destItemPath)) { + throw new DavException(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); - } + } + } catch (IOException ioe) { + // TODO: correct? + log.error("Error while moving resource: " + ioe.toString()); + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, ioe.getMessage()); - } + } + } /** * @see DavResource#copy(DavResource, boolean) @@ -628,16 +631,17 @@ } // make sure, that src and destination belong to the same workspace checkSameWorkspace(destination.getLocator()); - try { - String destItemPath = destination.getLocator().getRepositoryPath(); + String destItemPath = destination.getLocator().getRepositoryPath(); - getJcrSession().getWorkspace().copy(locator.getRepositoryPath(), destItemPath); - } catch (PathNotFoundException e) { - // according to rfc 2518: missing parent - throw new DavException(DavServletResponse.SC_CONFLICT, e.getMessage()); - } catch (RepositoryException e) { - throw new JcrDavException(e); + try { + if (!config.getCopyMoveManager().copyContent(getJcrSession(), locator, destItemPath)) { + throw new DavException(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); - } + } + } catch (IOException ioe) { + // TODO: correct? + log.error("Error while copying resource: " + ioe.toString()); + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, ioe.getMessage()); - } + } + } /** * @param type Index: src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java =================================================================== --- src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java (revision 1156078) +++ src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java (revision ) @@ -31,6 +31,9 @@ import javax.jcr.RepositoryException; import javax.xml.parsers.ParserConfigurationException; +import org.apache.jackrabbit.server.io.CopyMoveHandler; +import org.apache.jackrabbit.server.io.CopyMoveManager; +import org.apache.jackrabbit.server.io.CopyMoveManagerImpl; import org.apache.jackrabbit.server.io.DefaultIOManager; import org.apache.jackrabbit.server.io.IOHandler; import org.apache.jackrabbit.server.io.IOManager; @@ -59,6 +62,9 @@ private static final String ELEMENT_PROPERTYMANAGER = "propertymanager"; private static final String ELEMENT_PROPERTYHANDLER = "propertyhandler"; + private static final String ELEMENT_COPYMOVEMANAGER = "copymovemanager"; + private static final String ELEMENT_COPYMOVEHANDLER = "copymovehandler"; + private static final String ELEMENT_CLASS = "class"; private static final String ELEMENT_PARAM = "param"; @@ -72,6 +78,7 @@ private ItemFilter itemFilter; private IOManager ioManager; + private CopyMoveManager cmManager; private PropertyManager propManager; private String[] nodetypeNames = new String[0]; private boolean collectionNames = false; @@ -225,6 +232,33 @@ log.debug("'propertymanager' element is missing."); } + // copymovemanager config entry + el = DomUtil.getChildElement(config, ELEMENT_COPYMOVEMANAGER, null); + if (el != null) { + Object inst = buildClassFromConfig(el); + if (inst != null && inst instanceof CopyMoveManager) { + cmManager = (CopyMoveManager)inst; + // get optional 'iohandler' child elements and populate the + // ioManager with the instances + ElementIterator iohElements = DomUtil.getChildren(el, ELEMENT_COPYMOVEHANDLER, null); + while (iohElements.hasNext()) { + Element iohEl = iohElements.nextElement(); + inst = buildClassFromConfig(iohEl); + if (inst != null && inst instanceof CopyMoveHandler) { + CopyMoveHandler handler = (CopyMoveHandler) inst; + setParameters(handler, iohEl); + cmManager.addCopyMoveHandler(handler); + } else { + log.warn("Not a valid CopyMoveHandler : " + getClassName(iohEl)); + } + } + } else { + log.warn("'copymovemanager' element does not define a valid CopyMoveManager."); + } + } else { + log.debug("'copymovemanager' element is missing."); + } + // collection/non-collection config entry el = DomUtil.getChildElement(config, "collection", null); if (el != null) { @@ -427,6 +461,18 @@ } /** + * + * @return + */ + public CopyMoveManager getCopyMoveManager() { + if (cmManager == null) { + log.debug("Missing copymove-manager > building default."); + cmManager = CopyMoveManagerImpl.getDefaultManager(); + } + return cmManager; + } + + /** * Returns true, if the given item represents a {@link Node node} that is * either any of the nodetypes specified to represent a collection or * none of the nodetypes specified to represent a non-collection, respectively. Index: src/main/java/org/apache/jackrabbit/server/io/CopyMoveHandler.java =================================================================== --- src/main/java/org/apache/jackrabbit/server/io/CopyMoveHandler.java (revision ) +++ src/main/java/org/apache/jackrabbit/server/io/CopyMoveHandler.java (revision ) @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.jackrabbit.server.io; + +import org.apache.jackrabbit.webdav.DavResourceLocator; + +import javax.jcr.Session; +import java.io.IOException; + +/** + * CopyMoveHandler... + */ +public interface CopyMoveHandler { + + public boolean canCopy(DavResourceLocator locator, String dstPath) throws IOException; + + public boolean copyContent(Session session, DavResourceLocator locator, String dstPath) throws IOException; + + public boolean canMove(DavResourceLocator locator, String dstPath) throws IOException; + + public boolean moveContent(Session session, DavResourceLocator locator, String dstPath) throws IOException; +}