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