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 *     Nuxeo - initial API and implementation
016 *
017 * $Id$
018 */
019
020package org.nuxeo.ecm.webdav.resource;
021
022import static javax.ws.rs.core.Response.Status.OK;
023
024import java.io.IOException;
025import java.net.URI;
026import java.util.ArrayList;
027import java.util.List;
028
029import javax.servlet.http.HttpServletRequest;
030import javax.ws.rs.GET;
031import javax.ws.rs.HeaderParam;
032import javax.ws.rs.Produces;
033import javax.ws.rs.core.Context;
034import javax.ws.rs.core.Response;
035import javax.ws.rs.core.UriBuilder;
036import javax.ws.rs.core.UriInfo;
037import javax.xml.bind.JAXBException;
038import javax.xml.bind.Unmarshaller;
039
040import net.java.dev.webdav.jaxrs.methods.PROPFIND;
041import net.java.dev.webdav.jaxrs.xml.elements.HRef;
042import net.java.dev.webdav.jaxrs.xml.elements.MultiStatus;
043import net.java.dev.webdav.jaxrs.xml.elements.Prop;
044import net.java.dev.webdav.jaxrs.xml.elements.PropFind;
045import net.java.dev.webdav.jaxrs.xml.elements.PropStat;
046import net.java.dev.webdav.jaxrs.xml.elements.Status;
047import net.java.dev.webdav.jaxrs.xml.properties.LockDiscovery;
048import net.java.dev.webdav.jaxrs.xml.properties.SupportedLock;
049
050import org.apache.commons.httpclient.URIException;
051import org.apache.commons.httpclient.util.URIUtil;
052import org.apache.commons.lang.StringEscapeUtils;
053import org.apache.commons.logging.Log;
054import org.apache.commons.logging.LogFactory;
055import org.nuxeo.ecm.core.api.DocumentModel;
056import org.nuxeo.ecm.webdav.backend.Backend;
057import org.nuxeo.ecm.webdav.jaxrs.IsFolder;
058import org.nuxeo.ecm.webdav.jaxrs.Util;
059
060/**
061 * A resource for folder-like objects in the repository.
062 */
063public class FolderResource extends ExistingResource {
064
065    private static final Log log = LogFactory.getLog(FolderResource.class);
066
067    public FolderResource(String path, DocumentModel doc, HttpServletRequest request, Backend backend) {
068        super(path, doc, request, backend);
069    }
070
071    @GET
072    @Produces("text/html")
073    public String get() {
074        StringBuilder sb = new StringBuilder();
075        sb.append("<html><body><p>");
076        sb.append("Folder listing for ");
077        sb.append(path);
078        sb.append("/");
079        sb.append("</p>\n<ul>\n");
080        List<DocumentModel> children = backend.getChildren(doc.getRef());
081        for (DocumentModel child : children) {
082            String name = backend.getDisplayName(child);
083            String qname = StringEscapeUtils.escapeHtml(name);
084            sb.append("<li><a href=\"");
085            sb.append(qname);
086            if (child.isFolder()) {
087                sb.append("/");
088            }
089            sb.append("\">");
090            sb.append(qname);
091            sb.append("</a></li>\n");
092        }
093        sb.append("</ul></body>\n");
094        return sb.toString();
095    }
096
097    @PROPFIND
098    public Response propfind(@Context UriInfo uriInfo, @HeaderParam("depth") String depth) throws IOException,
099            JAXBException {
100
101        if (depth == null) {
102            depth = "1";
103        }
104
105        Unmarshaller u = Util.getUnmarshaller();
106
107        Prop prop = null;
108        if (request.getInputStream() != null && request.getContentLength() > 0) {
109            PropFind propFind;
110            try {
111                propFind = (PropFind) u.unmarshal(request.getInputStream());
112            } catch (JAXBException e) {
113                log.error(e);
114                // FIXME: check this is the right response code
115                return Response.status(400).build();
116            }
117            prop = propFind.getProp();
118            // Util.printAsXml(prop);
119        }
120
121        final net.java.dev.webdav.jaxrs.xml.elements.Response response;
122        response = createResponse(doc, uriInfo, prop, false);
123
124        if (!doc.isFolder() || depth.equals("0")) {
125            return Response.status(207).entity(new MultiStatus(response)).build();
126        }
127
128        List<net.java.dev.webdav.jaxrs.xml.elements.Response> responses = new ArrayList<net.java.dev.webdav.jaxrs.xml.elements.Response>();
129        responses.add(response);
130
131        List<DocumentModel> children = backend.getChildren(doc.getRef());
132        for (DocumentModel child : children) {
133            net.java.dev.webdav.jaxrs.xml.elements.Response childResponse;
134            childResponse = createResponse(child, uriInfo, prop);
135
136            responses.add(childResponse);
137        }
138
139        MultiStatus st = new MultiStatus(
140                responses.toArray(new net.java.dev.webdav.jaxrs.xml.elements.Response[responses.size()]));
141        // printXml(st);
142        return Response.status(207).entity(st).build();
143    }
144
145    protected net.java.dev.webdav.jaxrs.xml.elements.Response createResponse(DocumentModel doc, UriInfo uriInfo,
146            Prop prop) throws URIException {
147        return createResponse(doc, uriInfo, prop, true);
148    }
149
150    protected net.java.dev.webdav.jaxrs.xml.elements.Response createResponse(DocumentModel doc, UriInfo uriInfo,
151            Prop prop, boolean append) throws URIException {
152        PropStatBuilderExt props = getPropStatBuilderExt(doc, uriInfo);
153        PropStat propStatFound = props.build();
154        PropStat propStatNotFound = null;
155        if (prop != null) {
156            propStatNotFound = props.notFound(prop);
157        }
158
159        net.java.dev.webdav.jaxrs.xml.elements.Response response;
160        UriBuilder uriBuilder = uriInfo.getRequestUriBuilder();
161        if (append) {
162            uriBuilder.path(URIUtil.encodePath(backend.getDisplayName(doc)));
163        }
164        URI uri = uriBuilder.build();
165        if (doc.isFolder()) {
166            PropStat folderPropStat = new PropStat(
167                    new Prop(new LockDiscovery(), new SupportedLock(), new IsFolder("t")), new Status(OK));
168            if (propStatNotFound != null) {
169                response = new net.java.dev.webdav.jaxrs.xml.elements.Response(new HRef(uri), null, null, null,
170                        propStatFound, propStatNotFound, folderPropStat);
171            } else {
172                response = new net.java.dev.webdav.jaxrs.xml.elements.Response(new HRef(uri), null, null, null,
173                        propStatFound, folderPropStat);
174            }
175        } else {
176            if (propStatNotFound != null) {
177                response = new net.java.dev.webdav.jaxrs.xml.elements.Response(new HRef(uri), null, null, null,
178                        propStatFound, propStatNotFound);
179            } else {
180                response = new net.java.dev.webdav.jaxrs.xml.elements.Response(new HRef(uri), null, null, null,
181                        propStatFound);
182            }
183        }
184        return response;
185    }
186
187}