001/*
002 * (C) Copyright 2006-2009 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Stefane Fermigier
016 */
017package org.nuxeo.ecm.webdav.resource;
018
019import java.io.IOException;
020import java.net.URI;
021import java.net.URISyntaxException;
022
023import javax.servlet.http.HttpServletRequest;
024import javax.ws.rs.DELETE;
025import javax.ws.rs.HEAD;
026import javax.ws.rs.PUT;
027import javax.ws.rs.WebApplicationException;
028import javax.ws.rs.core.Response;
029
030import net.java.dev.webdav.jaxrs.methods.COPY;
031import net.java.dev.webdav.jaxrs.methods.MKCOL;
032import net.java.dev.webdav.jaxrs.methods.MOVE;
033import net.java.dev.webdav.jaxrs.methods.PROPFIND;
034import net.java.dev.webdav.jaxrs.methods.PROPPATCH;
035
036import org.nuxeo.ecm.core.api.Blob;
037import org.nuxeo.ecm.core.api.Blobs;
038import org.nuxeo.ecm.webdav.backend.Backend;
039
040/**
041 * Resource for an unknown (ie non-existing) object. Used so that PUT / MKCOL requests can actually created a document /
042 * folder. Other requests will end up with a 404 error.
043 */
044public class UnknownResource extends AbstractResource {
045
046    private static final String DS_STORE = ".DS_Store";
047
048    protected Backend backend;
049
050    public UnknownResource(String path, HttpServletRequest request, Backend backend) {
051        super(path, request);
052        this.backend = backend;
053    }
054
055    /**
056     * PUT over a non-existing resource: create a new file resource.
057     */
058    @PUT
059    public Response put() throws IOException, URISyntaxException {
060
061        // Special case: ignore some Mac OS X files.
062        // ._ files cannot easily be skipped as the Finder requires them on creation
063        // We only forbid .DS_Store creation for now.
064        if (DS_STORE.equals(name)) {
065            throw new WebApplicationException(Response.Status.CONFLICT);
066        }
067
068        ensureParentExists();
069        String contentType = request.getContentType();
070        if (contentType == null) {
071            contentType = "application/octet-stream";
072        }
073        Blob content = Blobs.createBlob(request.getInputStream(), contentType, null);
074        content.setFilename(name);
075        backend.createFile(parentPath, name, content);
076        backend.saveChanges();
077        return Response.created(new URI(request.getRequestURI())).build();
078    }
079
080    /**
081     * MKCOL over a non-existing resource: create a new folder resource.
082     */
083    @MKCOL
084    public Response mkcol() throws IOException, URISyntaxException {
085        ensureParentExists();
086        backend.createFolder(parentPath, name);
087        backend.saveChanges();
088        return Response.created(new URI(request.getRequestURI())).build();
089    }
090
091    // All these methods should raise an error 404
092
093    @DELETE
094    public Response delete() {
095        throw new WebApplicationException(Response.Status.NOT_FOUND);
096    }
097
098    @COPY
099    public Response copy() {
100        throw new WebApplicationException(Response.Status.NOT_FOUND);
101    }
102
103    @MOVE
104    public Response move() {
105        throw new WebApplicationException(Response.Status.NOT_FOUND);
106    }
107
108    @PROPFIND
109    public Response propfind() {
110        throw new WebApplicationException(Response.Status.NOT_FOUND);
111    }
112
113    @PROPPATCH
114    public Response proppatch() {
115        throw new WebApplicationException(Response.Status.NOT_FOUND);
116    }
117
118    @HEAD
119    public Response head() {
120        throw new WebApplicationException(Response.Status.NOT_FOUND);
121    }
122
123    // Utility
124
125    private void ensureParentExists() {
126        if (!backend.exists(parentPath)) {
127            throw new WebApplicationException(Response.Status.CONFLICT);
128        }
129    }
130
131}