001/*
002 * (C) Copyright 2006-2009 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Stefane Fermigier
018 */
019package org.nuxeo.ecm.webdav.resource;
020
021import java.io.IOException;
022import java.net.URI;
023import java.net.URISyntaxException;
024
025import javax.servlet.http.HttpServletRequest;
026import javax.ws.rs.DELETE;
027import javax.ws.rs.HEAD;
028import javax.ws.rs.PUT;
029import javax.ws.rs.WebApplicationException;
030import javax.ws.rs.core.Response;
031
032import net.java.dev.webdav.jaxrs.methods.COPY;
033import net.java.dev.webdav.jaxrs.methods.MKCOL;
034import net.java.dev.webdav.jaxrs.methods.MOVE;
035import net.java.dev.webdav.jaxrs.methods.PROPFIND;
036import net.java.dev.webdav.jaxrs.methods.PROPPATCH;
037
038import org.nuxeo.ecm.core.api.Blob;
039import org.nuxeo.ecm.core.api.Blobs;
040import org.nuxeo.ecm.webdav.backend.Backend;
041
042/**
043 * Resource for an unknown (ie non-existing) object. Used so that PUT / MKCOL requests can actually created a document /
044 * folder. Other requests will end up with a 404 error.
045 */
046public class UnknownResource extends AbstractResource {
047
048    private static final String DS_STORE = ".DS_Store";
049
050    protected Backend backend;
051
052    public UnknownResource(String path, HttpServletRequest request, Backend backend) {
053        super(path, request);
054        this.backend = backend;
055    }
056
057    /**
058     * PUT over a non-existing resource: create a new file resource.
059     */
060    @PUT
061    public Response put() throws IOException, URISyntaxException {
062
063        // Special case: ignore some Mac OS X files.
064        // ._ files cannot easily be skipped as the Finder requires them on creation
065        // We only forbid .DS_Store creation for now.
066        if (DS_STORE.equals(name)) {
067            throw new WebApplicationException(Response.Status.CONFLICT);
068        }
069
070        ensureParentExists();
071        String contentType = request.getContentType();
072        if (contentType == null) {
073            contentType = "application/octet-stream";
074        }
075        Blob content = Blobs.createBlob(request.getInputStream(), contentType, null);
076        content.setFilename(name);
077        backend.createFile(parentPath, name, content);
078        backend.saveChanges();
079        return Response.created(new URI(request.getRequestURI())).build();
080    }
081
082    /**
083     * MKCOL over a non-existing resource: create a new folder resource.
084     */
085    @MKCOL
086    public Response mkcol() throws IOException, URISyntaxException {
087        ensureParentExists();
088        backend.createFolder(parentPath, name);
089        backend.saveChanges();
090        return Response.created(new URI(request.getRequestURI())).build();
091    }
092
093    // All these methods should raise an error 404
094
095    @DELETE
096    public Response delete() {
097        throw new WebApplicationException(Response.Status.NOT_FOUND);
098    }
099
100    @COPY
101    public Response copy() {
102        throw new WebApplicationException(Response.Status.NOT_FOUND);
103    }
104
105    @MOVE
106    public Response move() {
107        throw new WebApplicationException(Response.Status.NOT_FOUND);
108    }
109
110    @PROPFIND
111    public Response propfind() {
112        throw new WebApplicationException(Response.Status.NOT_FOUND);
113    }
114
115    @PROPPATCH
116    public Response proppatch() {
117        throw new WebApplicationException(Response.Status.NOT_FOUND);
118    }
119
120    @HEAD
121    public Response head() {
122        throw new WebApplicationException(Response.Status.NOT_FOUND);
123    }
124
125    // Utility
126
127    private void ensureParentExists() {
128        if (!backend.exists(parentPath)) {
129            throw new WebApplicationException(Response.Status.CONFLICT);
130        }
131    }
132
133}