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 *     Nuxeo - initial API and implementation
018 *
019 * $Id$
020 */
021
022package org.nuxeo.ecm.webdav.resource;
023
024import java.io.IOException;
025import java.io.UnsupportedEncodingException;
026import java.net.URISyntaxException;
027
028import javax.servlet.http.HttpServletRequest;
029import javax.ws.rs.GET;
030import javax.ws.rs.HeaderParam;
031import javax.ws.rs.OPTIONS;
032import javax.ws.rs.Path;
033import javax.ws.rs.PathParam;
034import javax.ws.rs.Produces;
035import javax.ws.rs.WebApplicationException;
036import javax.ws.rs.core.Context;
037import javax.ws.rs.core.Response;
038import javax.ws.rs.core.UriInfo;
039import javax.xml.bind.JAXBException;
040
041import net.java.dev.webdav.jaxrs.methods.PROPFIND;
042
043import org.apache.commons.logging.Log;
044import org.apache.commons.logging.LogFactory;
045import org.nuxeo.ecm.core.api.Blob;
046import org.nuxeo.ecm.core.api.DocumentModel;
047import org.nuxeo.ecm.core.api.DocumentNotFoundException;
048import org.nuxeo.ecm.core.api.NuxeoException;
049import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
050import org.nuxeo.ecm.core.api.security.SecurityConstants;
051import org.nuxeo.ecm.webdav.backend.Backend;
052import org.nuxeo.ecm.webdav.backend.BackendHelper;
053
054//path is set at the servlet level, see the deployment-fragment file
055@Path("")
056public class RootResource {
057
058    private static final Log log = LogFactory.getLog(RootResource.class);
059
060    private HttpServletRequest request;
061
062    public RootResource(@Context HttpServletRequest request) {
063        log.debug(request.getMethod() + " " + request.getRequestURI());
064        this.request = request;
065    }
066
067    @GET
068    @Produces("text/html")
069    public Object getRoot() {
070        Object resource = findResource("");
071        if (resource instanceof FolderResource) {
072            return ((FolderResource) resource).get();
073        } else {
074            return ((VirtualFolderResource) findResource("")).get();
075        }
076    }
077
078    @OPTIONS
079    public Object getRootOptions() {
080        Object resource = findResource("");
081        if (resource instanceof FolderResource) {
082            return ((FolderResource) resource).options();
083        } else {
084            return ((VirtualFolderResource) findResource("")).options();
085        }
086    }
087
088    @PROPFIND
089    @Produces({ "application/xml", "text/xml" })
090    public Object getRootPropfind(@Context UriInfo uriInfo, @HeaderParam("depth") String depth)
091            throws IOException, JAXBException, URISyntaxException {
092        Object resource = findResource("");
093        if (resource instanceof FolderResource) {
094            return ((FolderResource) resource).propfind(uriInfo, depth);
095        } else {
096            return ((VirtualFolderResource) findResource("")).propfind(uriInfo, depth);
097        }
098    }
099
100    @Path("{path:.+}")
101    public Object findResource(@PathParam("path") String path) {
102        try {
103            path = new String(path.getBytes(), "UTF-8");
104        } catch (UnsupportedEncodingException e) {
105            throw new NuxeoException(e);
106        }
107
108        Backend backend = BackendHelper.getBackend(path, request);
109
110        if (backend == null) {
111            throw new WebApplicationException(Response.Status.NOT_FOUND);
112        }
113
114        if (backend.isVirtual()) {
115            return new VirtualFolderResource(path, request, backend.getVirtualFolderNames());
116        }
117
118        DocumentModel doc = null;
119        try {
120            doc = backend.getDocument(path);
121        } catch (DocumentNotFoundException e) {
122            log.error("Error during resolving path: " + path, e);
123            throw new WebApplicationException(Response.Status.CONFLICT);
124        }
125
126        if (doc == null) {
127            return new UnknownResource(path, request, backend);
128        }
129
130        // Send 401 error if not authorised to read.
131        if (!backend.hasPermission(doc.getRef(), SecurityConstants.READ)) {
132            throw new WebApplicationException(Response.Status.UNAUTHORIZED);
133        }
134
135        if (doc.isFolder()) {
136            return new FolderResource(getDocumentPath(doc), doc, request, backend);
137        } else {
138            return new FileResource(getDocumentPath(doc), doc, request, backend);
139        }
140    }
141
142    private String getDocumentPath(DocumentModel source) {
143        if (source.isFolder()) {
144            return source.getPathAsString();
145        } else {
146            BlobHolder bh = source.getAdapter(BlobHolder.class);
147            if (bh != null) {
148                Blob blob = bh.getBlob();
149                if (blob != null) {
150                    return blob.getFilename();
151                }
152            }
153            return String.valueOf(source.getPropertyValue("dc:title"));
154        }
155    }
156
157}