/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.xpn.xwiki.plugin.webdav.resources.domain; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.jackrabbit.server.io.IOUtil; import org.apache.jackrabbit.webdav.DavConstants; import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.DavResource; import org.apache.jackrabbit.webdav.DavResourceIterator; import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; import org.apache.jackrabbit.webdav.DavServletResponse; import org.apache.jackrabbit.webdav.io.InputContext; import org.apache.jackrabbit.webdav.io.OutputContext; import org.apache.jackrabbit.webdav.property.DavPropertyName; import org.apache.jackrabbit.webdav.property.DefaultDavProperty; import com.xpn.xwiki.plugin.webdav.resources.XWikiDavResource; import com.xpn.xwiki.plugin.webdav.resources.partial.AbstractDavResource; /** * Resource used to represent temporary resources demanded by various dav clients. * * @version $Id: 0b7d4746850c6a6fa0794ca48e1bf874e12d59d0 $ */ public class DavTempFile extends AbstractDavResource { /** * Flag indicating whether this resource is a collection. */ private boolean isCollection; /** * Content of this resource (file). */ private byte[] data; /** * Indicates if this resource has been created or not. Here creation means if the resource has been actually PUT / * MKCOL by the client as opposed to being initialized. This flag will be set to true once setModified() has been * invoked for the first time. */ private boolean created; /** * Created on. */ private Date timeOfCreation; /** * Last modified. */ private Date timeOfLastModification; /** * Default constructor. */ public DavTempFile() { timeOfCreation = new Date(IOUtil.UNDEFINED_TIME); timeOfLastModification = (Date) timeOfCreation.clone(); } @Override public void init(XWikiDavResource parent, String name, String relativePath) throws DavException { super.init(parent, name, relativePath); String strTimeOfCreation = DavConstants.creationDateFormat.format(timeOfCreation); getProperties().add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, strTimeOfCreation)); String strTimeOfModification = DavConstants.modificationDateFormat.format(timeOfLastModification); getProperties().add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, strTimeOfModification)); getProperties().add(new DefaultDavProperty(DavPropertyName.GETETAG, strTimeOfModification)); getProperties().add(new DefaultDavProperty(DavPropertyName.GETCONTENTLANGUAGE, "en")); String contentType = isCollection() ? "text/directory" : "application/octet-stream"; getProperties().add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, contentType)); int contentLength = (data != null) ? data.length : 0; getProperties().add(new DefaultDavProperty(DavPropertyName.GETCONTENTLENGTH, contentLength)); } @Override public XWikiDavResource decode(String[] tokens, int next) throws DavException { return super.decode(tokens, next); } @Override public boolean exists() { return parentResource.getVirtualMembers().contains(this); } @Override public void spool(OutputContext outputContext) throws IOException { outputContext.setContentLanguage("en"); outputContext.setContentLength(data != null ? data.length : 0); outputContext.setContentType(isCollection() ? "text/directory" : "application/octet-stream"); outputContext.setETag(DavConstants.modificationDateFormat.format(getModificationTime())); outputContext.setModificationTime(getModificationTime()); if (exists() && !isCollection()) { OutputStream out = outputContext.getOutputStream(); if (out != null) { out.write(this.data); out.flush(); } } } @Override public DavResourceIterator getMembers() { List<DavResource> children = new ArrayList<DavResource>(); children.addAll(getVirtualMembers()); return new DavResourceIteratorImpl(children); } @Override public void addMember(DavResource resource, InputContext inputContext) throws DavException { if (resource instanceof DavTempFile) { addVirtualMember(resource, inputContext); } else { throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); } } @Override public void removeMember(DavResource resource) throws DavException { if (resource instanceof DavTempFile) { removeVirtualMember(resource); } else { throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); } } @Override public void move(DavResource destination) throws DavException { if (destination instanceof DavTempFile && destination.getCollection().equals(getCollection()) && !destination.isCollection() && !isCollection()) { // A file rename operation DavTempFile destTempFile = (DavTempFile) destination; parentResource.getVirtualMembers().remove(this); parentResource.getVirtualMembers().add(destTempFile); destTempFile.update(this.data.clone(), this.timeOfLastModification); } else { throw new DavException(DavServletResponse.SC_FORBIDDEN); } clearCache(); } /** * @param data Data to be set as the content of this temporary file. * @param modificationTime Time of modification. */ public void update(byte[] data, Date modificationTime) { this.data = data.clone(); setModified(modificationTime); getProperties().add(new DefaultDavProperty(DavPropertyName.GETCONTENTLENGTH, this.data.length)); } /** * Changes the time of modification of this resource. * * @param modificationTime Time of modification. */ public void setModified(Date modificationTime) { if (!created) { timeOfCreation = (Date) modificationTime.clone(); String strTimeOfCreation = DavConstants.creationDateFormat.format(timeOfCreation); getProperties().add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, strTimeOfCreation)); created = true; } timeOfLastModification = (Date) modificationTime.clone(); String strTimeOfModification = DavConstants.modificationDateFormat.format(timeOfLastModification); getProperties().add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, strTimeOfModification)); getProperties().add(new DefaultDavProperty(DavPropertyName.GETETAG, String.valueOf(timeOfLastModification))); } /** * Sets the isCollection flag to true. */ public void setCollection() { this.isCollection = true; } @Override public boolean isCollection() { return isCollection; } @Override public long getModificationTime() { return timeOfLastModification.getTime(); } }