/* * 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 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.DavResourceIterator; import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; import org.apache.jackrabbit.webdav.MultiStatusResponse; import org.apache.jackrabbit.webdav.util.HttpDateFormat; import org.apache.jackrabbit.webdav.io.InputContext; 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.property.DavProperty; import org.apache.jackrabbit.webdav.property.PropEntry; 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; 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 java.util.ArrayList; import java.util.List; /** * <code>VersionResourceImpl</code> 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."); } } //--------------------------------------------------------< DavResource >--- /** * Since this implementation of <code>VersionResource</code> never is a * version belonging to a version controlled collection, this method always * returns <code>false</code> not respecting the configuration. * * @return always false */ @Override public boolean isCollection() { return false; } /** * @return An empty <code>DavResourceIterator</code> */ @Override public DavResourceIterator getMembers() { return DavResourceIteratorImpl.EMPTY; } /** * The version storage is read-only -> fails with 403. * * @see DavResource#addMember(DavResource, InputContext) */ @Override public void addMember(DavResource member, InputContext inputContext) throws DavException { throw new DavException(DavServletResponse.SC_FORBIDDEN); } /** * The version storage is read-only -> fails with 403. * * @see DavResource#removeMember(DavResource) */ @Override public void removeMember(DavResource member) throws DavException { throw new DavException(DavServletResponse.SC_FORBIDDEN); } /** * Version storage is read-only -> fails with 403. * * @see DavResource#setProperty(DavProperty) */ @Override public void setProperty(DavProperty<?> property) throws DavException { throw new DavException(DavServletResponse.SC_FORBIDDEN); } /** * Version storage is read-only -> fails with 403. * * @see DavResource#removeProperty(DavPropertyName) */ @Override public void removeProperty(DavPropertyName propertyName) throws DavException { throw new DavException(DavServletResponse.SC_FORBIDDEN); } /** * Version storage is read-only -> fails with 403. * * @see DavResource#alterProperties(List) */ @Override public MultiStatusResponse alterProperties(List<? extends PropEntry> changeList) throws DavException { throw new DavException(DavServletResponse.SC_FORBIDDEN); } //----------------------------------------------------< VersionResource >--- /** * 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 { // severe error since resource factory doesn't behave correctly. throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); } } 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 */ @Override protected void initSupportedReports() { super.initSupportedReports(); if (exists()) { supportedReports.addReportType(ReportType.VERSION_TREE); } } /** * Fill the property set for this resource. */ @Override protected void initProperties() { if (!propsInitialized) { super.initProperties(); Version v = (Version) getNode(); try { String creationDate = HttpDateFormat.creationDateFormat().format(v.getCreated().getTime()); // replace dummy creation date from default collection properties.add(new DefaultDavProperty<String>(DavPropertyName.CREATIONDATE, creationDate)); // required, protected DAV:version-name property properties.add(new DefaultDavProperty<String>(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, false)); properties.add(getHrefProperty(SUCCESSOR_SET, v.getSuccessors(), true, false)); // 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<Node> nodeList = new ArrayList<Node>(); 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, nodeList.toArray(new Node[nodeList.size()]), true, false)); } catch (RepositoryException e) { log.error(e.getMessage()); } } } }