Index: C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/server/io/DefaultIOManager.java =================================================================== --- C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/server/io/DefaultIOManager.java (revision 556115) +++ C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/server/io/DefaultIOManager.java (working copy) @@ -58,6 +58,7 @@ * */ protected void init() { + addIOHandler(new VersionHandler(this)); addIOHandler(new ZipHandler(this)); addIOHandler(new XmlHandler(this)); addIOHandler(new DirListingExportHandler(this)); Index: C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/server/io/VersionHandler.java =================================================================== --- C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/server/io/VersionHandler.java (revision 0) +++ C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/server/io/VersionHandler.java (revision 0) @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. 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 java.io.IOException; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.version.Version; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.simple.VersionResourceImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VersionHandler extends DefaultHandler implements IOHandler{ + + private static Logger log = LoggerFactory.getLogger(VersionHandler.class); + + public VersionHandler() { + } + + public VersionHandler(IOManager ioManager) { + super(ioManager); + } + + public VersionHandler(IOManager ioManager, String collectionNodetype, String defaultNodetype, String contentNodetype) { + super(ioManager, collectionNodetype, defaultNodetype, contentNodetype); + } + + public String getName() { + return "Version Handler"; + } + + public boolean canImport(ImportContext context, boolean isCollection) { + return false; + } + + public boolean canImport(ImportContext context, DavResource resource) { + return false; + } + + public boolean importContent(ImportContext context, boolean isCollection) throws IOException { + return false; + } + + public boolean importContent(ImportContext context, DavResource resource) throws IOException { + return false; + } + + + /** + * we can export only if the node is a Version node. + * @param context + * @param isCollection + * @return + */ + public boolean canExport(ExportContext context, boolean isCollection) { + if (context == null) { + return false; + } + return context.getExportRoot() instanceof Version; + } + + /** + * @return true if the specified resource is an instance of VersionResourceImpl. False otherwise. + * @see IOHandler#canExport(ExportContext, DavResource) + */ + public boolean canExport(ExportContext context, DavResource resource) { + if (resource == null) { + return false; + } + return resource instanceof VersionResourceImpl; + } + + /** + * Retrieves the content node that contains the data to be exported. + * + * @param context + * @param isCollection + * @return content node used for the export + * @throws javax.jcr.RepositoryException + */ + protected Node getContentNode(ExportContext context, boolean isCollection) throws RepositoryException { + Node node = (Node)context.getExportRoot(); + NodeIterator it = node.getNodes(JcrConstants.JCR_FROZENNODE); + + if (it.hasNext()) { + node = it.nextNode(); + return node.getNode(JcrConstants.JCR_CONTENT); + } + return null; + } +} Index: C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java =================================================================== --- C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (revision 556115) +++ C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (working copy) @@ -16,9 +16,30 @@ */ package org.apache.jackrabbit.webdav.simple; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +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.lock.Lock; + import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.server.io.AbstractExportContext; +import org.apache.jackrabbit.server.io.DefaultIOListener; import org.apache.jackrabbit.server.io.ExportContext; import org.apache.jackrabbit.server.io.ExportContextImpl; +import org.apache.jackrabbit.server.io.IOListener; import org.apache.jackrabbit.server.io.IOManager; import org.apache.jackrabbit.server.io.IOUtil; import org.apache.jackrabbit.server.io.ImportContext; @@ -23,12 +44,9 @@ import org.apache.jackrabbit.server.io.IOUtil; import org.apache.jackrabbit.server.io.ImportContext; import org.apache.jackrabbit.server.io.ImportContextImpl; -import org.apache.jackrabbit.server.io.PropertyManager; -import org.apache.jackrabbit.server.io.PropertyImportContext; -import org.apache.jackrabbit.server.io.IOListener; import org.apache.jackrabbit.server.io.PropertyExportContext; -import org.apache.jackrabbit.server.io.AbstractExportContext; -import org.apache.jackrabbit.server.io.DefaultIOListener; +import org.apache.jackrabbit.server.io.PropertyImportContext; +import org.apache.jackrabbit.server.io.PropertyManager; import org.apache.jackrabbit.util.Text; import org.apache.jackrabbit.webdav.DavConstants; import org.apache.jackrabbit.webdav.DavException; @@ -56,6 +74,7 @@ import org.apache.jackrabbit.webdav.property.DavProperty; import org.apache.jackrabbit.webdav.property.DavPropertyIterator; import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameIterator; import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; import org.apache.jackrabbit.webdav.property.DavPropertySet; import org.apache.jackrabbit.webdav.property.DefaultDavProperty; @@ -60,27 +79,9 @@ import org.apache.jackrabbit.webdav.property.DavPropertySet; import org.apache.jackrabbit.webdav.property.DefaultDavProperty; import org.apache.jackrabbit.webdav.property.ResourceType; -import org.apache.jackrabbit.webdav.property.DavPropertyNameIterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -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.lock.Lock; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Collections; - /** * DavResourceImpl implements a DavResource. */ @@ -104,7 +105,7 @@ private Node node; private DavResourceLocator locator; - private DavPropertySet properties = new DavPropertySet(); + protected DavPropertySet properties = new DavPropertySet(); private boolean inited = false; private boolean isCollection = true; @@ -120,6 +121,7 @@ * @param locator * @param factory * @param session + * @deprecated */ public DavResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config) throws DavException { @@ -150,6 +152,45 @@ } } + public DavResourceImpl(DavResourceLocator locator, DavResourceFactory factory, + DavSession session, ResourceConfig config, boolean isCollection) throws DavException { + this(locator, factory, session, config, null); + this.isCollection = isCollection; + } + + /** + * Create a new {@link DavResource}. + * + * @param locator + * @param factory + * @param session + * @param config + * @param node + * @throws DavException + */ + public DavResourceImpl(DavResourceLocator locator, DavResourceFactory factory, + DavSession session, ResourceConfig config, Node node) throws DavException { + JcrDavSession.checkImplementation(session); + this.session = (JcrDavSession)session; + this.factory = factory; + this.locator = locator; + this.filter = config.getItemFilter(); + this.ioManager = config.getIOManager(); + this.propManager = config.getPropertyManager(); + + if (locator == null || session == null || config == null) { + throw new IllegalArgumentException(); + } else if (locator.getResourcePath() != null) { + if (node != null) { + this.node = node; + // define what is a collection in webdav + isCollection = config.isCollectionResource(node); + } + } else { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + } + /** * @return DavResource#COMPLIANCE_CLASS * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() Index: C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java =================================================================== --- C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java (revision 0) +++ C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java (revision 0) @@ -0,0 +1,256 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. 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.webdav.simple; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.OptionsInfo; +import org.apache.jackrabbit.webdav.version.OptionsResponse; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The DeltaVResourceImpl encapsultes the functionality common to all + * DeltaV compliant resources. + */ +public class DeltaVResourceImpl extends DavResourceImpl implements DeltaVResource { + protected SupportedReportSetProperty supportedReports = new SupportedReportSetProperty(); + private static final Logger log = LoggerFactory.getLogger(DeltaVResourceImpl.class); + + + public DeltaVResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, (Node)item); + initSupportedReports(); + } + + public DeltaVResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, boolean isCollection) throws DavException { + super(locator, factory, session, config, isCollection); + initSupportedReports(); + } + protected void initSupportedReports() { + if (exists()) { + supportedReports.addReportType(ReportType.EXPAND_PROPERTY); + if (isCollection()) supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY); + } + } + + /** + * Fill the property set for this resource. + */ + protected void initProperties() { + super.initProperties(); + if (exists()) { + properties.add(supportedReports); + } + } + + /** + * @param optionsInfo + * @return object to be used in the OPTIONS response body or null + * @see DeltaVResource#getOptionResponse(org.apache.jackrabbit.webdav.version.OptionsInfo) + */ + public OptionsResponse getOptionResponse(OptionsInfo optionsInfo) { + OptionsResponse oR = null; + if (optionsInfo != null) { + oR = new OptionsResponse(); + // currently only DAV:version-history-collection-set is supported + if (optionsInfo.containsElement(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE)) { + String[] hrefs = new String[] { + getLocatorFromNodePath("/"+JcrConstants.JCR_SYSTEM+"/"+JcrConstants.JCR_VERSIONSTORAGE).getHref(true) + }; + oR.addEntry(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE, hrefs); + } + } + return oR; + } + + /** + * @param reportInfo + * @return the requested report + * @throws DavException + * @see DeltaVResource#getReport(org.apache.jackrabbit.webdav.version.report.ReportInfo) + */ + public Report getReport(ReportInfo reportInfo) throws DavException { + if (reportInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "A REPORT request must provide a valid XML request body."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + if (supportedReports.isSupportedReport(reportInfo)) { + Report report = ReportType.getType(reportInfo).createReport(this, reportInfo); + return report; + } else { + throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, "Unkown report "+ reportInfo.getReportName() +"requested."); + } + } + + /** + * The JCR api does not provide methods to create new workspaces. Calling + * addWorkspace on this resource will always fail. + * + * @param workspace + * @throws DavException Always throws. + * @see DeltaVResource#addWorkspace(org.apache.jackrabbit.webdav.DavResource) + */ + public void addWorkspace(DavResource workspace) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Return an array of DavResource objects that are referenced + * by the property with the specified name. + * + * @param hrefPropertyName + * @return array of DavResources + * @throws DavException + * @see DeltaVResource#getReferenceResources(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + public DavResource[] getReferenceResources(DavPropertyName hrefPropertyName) throws DavException { + DavProperty prop = getProperty(hrefPropertyName); + List resources = new ArrayList(); + if (prop != null && prop instanceof HrefProperty) { + HrefProperty hp = (HrefProperty)prop; + // process list of hrefs + List hrefs = hp.getHrefs(); + for (Iterator iter = hrefs.iterator(); iter.hasNext();) { + String href = (String)iter.next(); + DavResourceLocator locator = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), href); + resources.add(createResourceFromLocator(locator)); + } + } else { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + return (DavResource[])resources.toArray(new DavResource[0]); + } + + /** + * Build a DavResourceLocator from the given nodePath path. + * + * @param nodePath + * @return a new DavResourceLocator + * @see DavLocatorFactory#createResourceLocator(String, String, String) + */ + protected DavResourceLocator getLocatorFromNodePath(String nodePath) { + DavResourceLocator loc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), getLocator().getWorkspacePath(), nodePath, false); + return loc; + } + + + /** + * Build a new {@link DavResourceLocator} from the given repository node. + * + * @param repositoryNode + * @return a new locator for the specified node. + * @see #getLocatorFromNodePath(String) + */ + protected DavResourceLocator getLocatorFromNode(Node repositoryNode) { + String nodePath = null; + try { + if (repositoryNode != null) { + nodePath = repositoryNode.getPath(); + } + } catch (RepositoryException e) { + // ignore: should not occur + log.warn(e.getMessage()); + } + return getLocatorFromNodePath(nodePath); + } + + /** + * Create a new DavResource from the given locator. + * @param loc + * @return new DavResource + */ + protected DavResource createResourceFromLocator(DavResourceLocator loc) + throws DavException { + DavResource res = getFactory().createResource(loc, getSession()); + return res; + } + + /** + * Returns a {@link org.apache.jackrabbit.webdav.property.HrefProperty} with the + * specified property name and values. Each item present in the specified + * values array is referenced in the resulting property. + * + * @param name + * @param values + * @param isProtected + * @return HrefProperty + */ + protected HrefProperty getHrefProperty(DavPropertyName name, Node[] values, boolean isProtected) { + if (values == null) { + return null; + } + String[] pHref = new String[values.length]; + for (int i = 0; i < values.length; i++) { + pHref[i] = getLocatorFromNode(values[i]).getHref(true); + } + return new HrefProperty(name, pHref, isProtected); + } + + /** + * Returns a new {@link HrefProperty href property} to the property set, where + * all items present in the specifed iterator are referenced in the + * resulting property. + * + * @param name + * @param itemIterator + * @param isProtected + * @see #getHrefProperty(DavPropertyName, javax.jcr.Item[], boolean) + * @return HrefProperty + */ + protected HrefProperty getHrefProperty(DavPropertyName name, Iterator itemIterator, + boolean isProtected) { + ArrayList l = new ArrayList(); + while (itemIterator.hasNext()) { + l.add(itemIterator.next()); + } + return getHrefProperty(name, (Node[]) l.toArray(new Node[l.size()]), isProtected); + } + + /** + * @return DavResource#COMPLIANCE_CLASS + * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() + */ + public String getComplianceClass() { + return DavResource.COMPLIANCE_CLASS+", version-control"; + } +} Index: C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java =================================================================== --- C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java (revision 556115) +++ C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java (working copy) @@ -16,6 +16,13 @@ */ package org.apache.jackrabbit.webdav.simple; +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; + import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.DavMethods; import org.apache.jackrabbit.webdav.DavResource; @@ -24,7 +31,10 @@ import org.apache.jackrabbit.webdav.DavServletRequest; import org.apache.jackrabbit.webdav.DavServletResponse; import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; import org.apache.jackrabbit.webdav.lock.LockManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * ResourceFactoryImpl implements a simple DavResourceFactory @@ -30,6 +40,7 @@ * ResourceFactoryImpl implements a simple DavResourceFactory */ public class ResourceFactoryImpl implements DavResourceFactory { + private static Logger log =LoggerFactory.getLogger(ResourceFactoryImpl.class); private final LockManager lockMgr; private final ResourceConfig resourceConfig; @@ -64,7 +75,7 @@ * @param locator * @param request * @param response - * @return + * @return DavResource * @throws DavException * @see DavResourceFactory#createResource(DavResourceLocator, * DavServletRequest, DavServletResponse) @@ -71,11 +82,14 @@ */ public DavResource createResource(DavResourceLocator locator, DavServletRequest request, DavServletResponse response) throws DavException { - DavResourceImpl resource = (DavResourceImpl)createResource(locator, request.getDavSession()); - if (DavMethods.isCreateRequest(request) && ! resource.exists()) { - resource.setIsCollection(DavMethods.isCreateCollectionRequest(request)); + try { + Node node = getNode(request.getDavSession(), locator); + DavResource resource = createResource(node, locator, request.getDavSession(), request); + resource.addLockManager(lockMgr); + return resource; + } catch (RepositoryException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e); } - return resource; } /** @@ -89,8 +103,64 @@ * @see DavResourceFactory#createResource(DavResourceLocator, DavSession) */ public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException { - DavResourceImpl res = new DavResourceImpl(locator, this, session, resourceConfig); - res.addLockManager(lockMgr); - return res; + try { + Node node = getNode(session, locator); + DavResource resource = createResource(node, locator, session, null); + resource.addLockManager(lockMgr); + return resource; + } catch (RepositoryException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e); + } + } + + private Node getNode(DavSession sessionImpl, DavResourceLocator locator) + throws RepositoryException { + Node node = null; + try { + Item item = ((JcrDavSession)sessionImpl).getRepositorySession().getItem(locator.getRepositoryPath()); + if (item instanceof Node) { + node = (Node)item; + } + } catch (PathNotFoundException e) { + node = null; + } + return node; + } + + /** + * Tries to retrieve the repository item defined by the locator's resource + * path and build the corresponding WebDAV resource. The following distinction + * is made between items: Version nodes, VersionHistory nodes, root node, + * unspecified nodes and finally property items. + * + * @param locator + * @param sessionImpl + * @return DavResource representing a repository item. + * @throws RepositoryException if {@link javax.jcr.Session#getItem(String)} fails. + */ + private DavResource createResource(Node node, DavResourceLocator locator, DavSession session, DavServletRequest request) throws RepositoryException, DavException { + JcrDavSession.checkImplementation(session); + JcrDavSession sessionImpl = (JcrDavSession)session; + + DavResource resource; + if (node != null) { + // create special resources for Version and VersionHistory + if (node instanceof Version) { + resource = new VersionResourceImpl(locator, this, sessionImpl, resourceConfig, node); + } else if (node instanceof VersionHistory) { + resource = new VersionHistoryResourceImpl(locator, this, sessionImpl, resourceConfig, node); + } else{ + resource = new VersionControlledResourceImpl(locator, this, sessionImpl, resourceConfig, node); + } + } + else { + log.info("Creating resource for non-existing repository node ..."); + if (request != null && DavMethods.isCreateRequest(request)) { + resource = new VersionControlledResourceImpl(locator, this, sessionImpl, resourceConfig, DavMethods.isCreateCollectionRequest(request)); + } else { + resource = new VersionControlledResourceImpl(locator, this, sessionImpl, resourceConfig, null); + } + } + return resource; } } Index: C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.java =================================================================== --- C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.java (revision 0) +++ C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.java (revision 0) @@ -0,0 +1,335 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. 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.webdav.simple; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.VersionableResource; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +/** + * VersionControlledResourceImpl represents a JCR node item and + * covers all functionality related to versioning of {@link Node}s. + * + * @see Node + */ +public class VersionControlledResourceImpl extends DeltaVResourceImpl + implements VersionControlledResource { + private static final Logger log = LoggerFactory.getLogger(VersionControlledResourceImpl.class); + + /** + * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. + * + * @param locator + * @param factory + * @param session + * @param config + * @param item + * @throws DavException + */ + public VersionControlledResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, item); + initSupportedReports(); + } + + /** + * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. + * + * @param locator + * @param factory + * @param session + * @param config + * @param isCollection + * @throws DavException + */ + public VersionControlledResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, boolean isCollection) throws DavException { + super(locator, factory, session, config, isCollection); + initSupportedReports(); + } + + //-------------------------------------------------------------------------- + /** + * Define the set of reports supported by this resource. + * + * @see SupportedReportSetProperty + */ + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY); + if (isVersionControlled()) { + supportedReports.addReportType(ReportType.VERSION_TREE); + } + } + } + + + /** + * Calls {@link javax.jcr.Node#checkin()} on the underlying repository node. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkin() + */ + public String checkin() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + try { + Version v = getNode().checkin(); + String versionHref = getLocatorFromNode(v).getHref(true); + return versionHref; + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + + //----------------------------------------------< DavResource interface >--- + /** + * Return a comma separated string listing the supported method names. + * + * @return the supported method names. + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + public String getSupportedMethods() { + StringBuffer sb = new StringBuffer(super.getSupportedMethods()); + // Versioning support + sb.append(", ").append(VersionableResource.METHODS); + if (isVersionControlled()) { + try { + if (getNode().isCheckedOut()) { + sb.append(", ").append(VersionControlledResource.methods_checkedOut); + } else { + sb.append(", ").append(VersionControlledResource.methods_checkedIn); + } + } catch (RepositoryException e) { + // should not occur. + log.error(e.getMessage()); + } + } + return sb.toString(); + } + + /** + * Calls {@link javax.jcr.Node#checkout()} on the underlying repository node. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkout() + */ + public void checkout() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + try { + getNode().checkout(); + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + + /** + * Not implemented. Always throws a DavException with error code + * {@link org.apache.jackrabbit.webdav.DavServletResponse#SC_NOT_IMPLEMENTED}. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#uncheckout() + */ + public void uncheckout() throws DavException { + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + + public MultiStatus update(UpdateInfo updateInfo) throws DavException { + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + + public MultiStatus merge(MergeInfo mergeInfo) throws DavException { + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + + /** + * Modify the labels present with the versions of this resource. + * + * @param labelInfo + * @throws DavException + * @see javax.jcr.version.VersionHistory#addVersionLabel(String, String, boolean) + * @see javax.jcr.version.VersionHistory#removeVersionLabel(String) + */ + public void label(LabelInfo labelInfo) throws DavException { + if (labelInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + if (!isVersionControlled() || getNode().isCheckedOut()) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "A LABEL request may only be applied to a version-controlled, checked-in resource."); + } + DavResource[] resArr = this.getReferenceResources(CHECKED_IN); + if (resArr.length == 1 && resArr[0] instanceof VersionResource) { + ((VersionResource)resArr[0]).label(labelInfo); + } else { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "DAV:checked-in property on '" + getHref() + "' did not point to a single VersionResource."); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Returns the {@link javax.jcr.version.VersionHistory} associated with the repository node. + * If the node is not versionable an exception is thrown. + * + * @return the {@link VersionHistoryResource} associated with this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#getVersionHistory() + * @see javax.jcr.Node#getVersionHistory() + */ + public VersionHistoryResource getVersionHistory() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + VersionHistory vh = getNode().getVersionHistory(); + DavResourceLocator loc = getLocatorFromNode(vh); + DavResource vhr = createResourceFromLocator(loc); + if (vhr instanceof VersionHistoryResource) { + return (VersionHistoryResource)vhr; + } else { + // TODO log message about not returning a version history resource + return null; + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //--------------------------------< VersionControlledResource interface >--- + /** + * Adds version control to this resource. If the resource is already under + * version control, this method has no effect. + * + * @throws org.apache.jackrabbit.webdav.DavException if this resource does not + * exist yet or if an error occurs while making the underlying node versionable. + * @see org.apache.jackrabbit.webdav.version.VersionableResource#addVersionControl() + */ + public void addVersionControl() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + Node item = getNode(); + try { + item.addMixin(JcrConstants.MIX_VERSIONABLE); + item.save(); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } // else: is already version controlled -> ignore + } + + + + /** + * Fill the property set for this resource. + */ + protected void initProperties() { + super.initProperties(); + if (exists()) { + Node n = getNode(); + // properties defined by RFC 3253 for version-controlled resources + if (isVersionControlled()) { + // workspace property already set in AbstractResource.initProperties() + try { + // DAV:version-history (computed) + String vhHref = getLocatorFromNode(n.getVersionHistory()).getHref(true); + properties.add(new HrefProperty(VERSION_HISTORY, vhHref, true)); + + // DAV:auto-version property: there is no auto version, explicit CHECKOUT is required. + properties.add(new DefaultDavProperty(AUTO_VERSION, null, false)); + + String baseVHref = getLocatorFromNode(n.getBaseVersion()).getHref(true); + if (n.isCheckedOut()) { + // DAV:checked-out property (protected) + properties.add(new HrefProperty(CHECKED_OUT, baseVHref, true)); + + // todo: checkout-fork, checkin-fork + } else { + // DAV:checked-in property (protected) + properties.add(new HrefProperty(CHECKED_IN, baseVHref, true)); + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + } + } + + /** + * @return true, if this resource represents an existing repository node + * that has the mixin nodetype 'mix:versionable' set. + */ + private boolean isVersionControlled() { + boolean vc = false; + if (exists()) { + Node item = getNode(); + try { + vc = item.isNodeType(JcrConstants.MIX_VERSIONABLE); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + } + return vc; + } + +} Index: C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.java =================================================================== --- C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.java (revision 0) +++ C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.java (revision 0) @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. 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.webdav.simple; + +import java.util.ArrayList; + +import javax.jcr.Item; +import javax.jcr.RepositoryException; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionIterator; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.ResourceType; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * VersionHistoryResourceImpl represents a JCR version history. + * + * @see VersionHistory + */ +public class VersionHistoryResourceImpl extends DeltaVResourceImpl implements VersionHistoryResource { + private static final Logger log = LoggerFactory.getLogger(VersionHistoryResourceImpl.class); + + public VersionHistoryResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, item); + if (getNode() == null || !(getNode() instanceof VersionHistory)) { + throw new IllegalArgumentException("VersionHistory item expected."); + } + } + + //-----------------------------------< VersionHistoryResource interface >--- + /** + * Return an array of {@link org.apache.jackrabbit.webdav.version.VersionResource}s representing all versions + * present in the underlying JCR version history. + * + * @return array of {@link org.apache.jackrabbit.webdav.version.VersionResource}s representing all versions + * present in the underlying JCR version history. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionHistoryResource#getVersions() + */ + public VersionResource[] getVersions() throws DavException { + try { + VersionIterator vIter = ((VersionHistory)getNode()).getAllVersions(); + ArrayList l = new ArrayList(); + while (vIter.hasNext()) { + DavResourceLocator versionLoc = getLocatorFromNode(vIter.nextVersion()); + DavResource vr = createResourceFromLocator(versionLoc); + if (vr instanceof VersionResource) { + l.add(vr); + } else { + // TODO log message about not returning a version resource + } + } + return (VersionResource[]) l.toArray(new VersionResource[l.size()]); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Removing a version resource is achieved by calling removeVersion + * on the versionhistory item this version belongs to. + * + * @throws DavException if the version does not exist or if an error occurs + * while deleting. + * @see DavResource#removeMember(org.apache.jackrabbit.webdav.DavResource) + */ + public void removeMember(DavResource member) throws DavException { + if (exists()) { + VersionHistory versionHistory = (VersionHistory) getNode(); + try { + String itemPath = member.getLocator().getRepositoryPath(); + // Retrieve the last segment of the given path and removes the index if present. + if (itemPath == null) { + throw new IllegalArgumentException("Cannot retrieve name from a 'null' item path."); + } + String name = Text.getName(itemPath); + // remove index + if (name.endsWith("]")) { + name = name.substring(0, name.lastIndexOf('[')); + } + versionHistory.removeVersion(name); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + } + + //-------------------------------------------------------------------------- + /** + * Fill the property set for this resource. + */ + protected void initProperties() { + super.initProperties(); + + // change resourcetype defined by default item collection + properties.add(new ResourceType(ResourceType.VERSION_HISTORY)); + + // required root-version property for version-history resource + try { + String rootVersionHref = getLocatorFromNode(((VersionHistory)getNode()).getRootVersion()).getHref(true); + properties.add(new HrefProperty(VersionHistoryResource.ROOT_VERSION, rootVersionHref, true)); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + + // required, protected version-set property for version-history resource + try { + VersionIterator vIter = ((VersionHistory)getNode()).getAllVersions(); + properties.add(getHrefProperty(VersionHistoryResource.VERSION_SET, vIter, true)); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + + +} Index: C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.java =================================================================== --- C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.java (revision 0) +++ C:/jprojects/eclipse/version_patch/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.java (revision 0) @@ -0,0 +1,208 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. 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.webdav.simple; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.RepositoryException; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.LabelSetProperty; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * VersionResourceImpl represents a JCR version. + * + * @see Version + */ +public class VersionResourceImpl extends DeltaVResourceImpl implements VersionResource { + private static final Logger log = LoggerFactory.getLogger(VersionResourceImpl.class); + + /** + * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. + * @param locator + * @param factory + * @param session + * @param config + * @param item + * @throws DavException + * + */ + public VersionResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, item); + if (getNode() == null || !(getNode() instanceof Version)) { + throw new IllegalArgumentException("Version item expected."); + } + } + + //------------------------------------------< VersionResource interface >--- + /** + * Modify the labels defined for the underlying repository version. + * + * @param labelInfo + * @throws org.apache.jackrabbit.webdav.DavException + * @see VersionResource#label(org.apache.jackrabbit.webdav.version.LabelInfo) + * @see javax.jcr.version.VersionHistory#addVersionLabel(String, String, boolean) + * @see javax.jcr.version.VersionHistory#removeVersionLabel(String) + */ + public void label(LabelInfo labelInfo) throws DavException { + if (labelInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + VersionHistory vh = getVersionHistoryItem(); + if (labelInfo.getType() == LabelInfo.TYPE_REMOVE) { + vh.removeVersionLabel(labelInfo.getLabelName()); + } else if (labelInfo.getType() == LabelInfo.TYPE_ADD) { + // ADD: only add if not yet existing + vh.addVersionLabel(getNode().getName(), labelInfo.getLabelName(), false); + } else { + // SET: move label if already existing + vh.addVersionLabel(getNode().getName(), labelInfo.getLabelName(), true); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Returns the {@link VersionHistory} associated with the repository version. + * Note: in contrast to a versionable node, the version history of a version + * item is always represented by its nearest ancestor. + * + * @return the {@link org.apache.jackrabbit.webdav.version.VersionHistoryResource} associated with this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionResource#getVersionHistory() + * @see javax.jcr.Item#getParent() + */ + public VersionHistoryResource getVersionHistory() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + VersionHistory vh = getVersionHistoryItem(); + DavResourceLocator loc = getLocatorFromNode(vh); + DavResource vhr = createResourceFromLocator(loc); + if (vhr instanceof VersionHistoryResource) { + return (VersionHistoryResource)vhr; + } else { + // TODO log message about not returning a version history resource + return null; + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Return versionhistory that contains this version item + * + * @return versionhistory that contains this version item + * @throws RepositoryException + * @see javax.jcr.version.Version#getContainingHistory() + */ + private VersionHistory getVersionHistoryItem() throws RepositoryException { + return ((Version)getNode()).getContainingHistory(); + } + + //-------------------------------------------------------------------------- + /** + * Define the set of reports supported by this resource. + * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ReportType.VERSION_TREE); + } + } + + /** + * Fill the property set for this resource. + */ + protected void initProperties() { + super.initProperties(); + + if (exists()) { + Version v = (Version)getNode(); + try { + String creationDate = DavConstants.creationDateFormat.format(v.getCreated().getTime()); + // replace dummy creation date from default collection + properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, creationDate)); + + // required, protected DAV:version-name property + properties.add(new DefaultDavProperty(VERSION_NAME, v.getName(), true)); + + // required, protected DAV:label-name-set property + String[] labels = getVersionHistoryItem().getVersionLabels(v); + properties.add(new LabelSetProperty(labels)); + + // required DAV:predecessor-set (protected) and DAV:successor-set (computed) properties + properties.add(getHrefProperty(VersionResource.PREDECESSOR_SET, v.getPredecessors(), true)); + properties.add(getHrefProperty(SUCCESSOR_SET, v.getSuccessors(), true)); + + // required DAV:version-history (computed) property + String vhHref = getLocatorFromNode(getVersionHistoryItem()).getHref(true); + properties.add(new HrefProperty(VersionResource.VERSION_HISTORY, vhHref, true)); + + // required DAV:checkout-set (computed) property + PropertyIterator it = v.getReferences(); + List nodeList = new ArrayList(); + while (it.hasNext()) { + Property p = it.nextProperty(); + if (JcrConstants.JCR_BASEVERSION.equals(p.getName())) { + Node n = p.getParent(); + if (n.isCheckedOut()) { + nodeList.add(n); + } + } + } + properties.add(getHrefProperty(CHECKOUT_SET, (Node[]) nodeList.toArray(new Node[nodeList.size()]), true)); + + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + } +}