001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (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 *     Gagnavarslan ehf
016 */
017package org.nuxeo.ecm.webdav.resource;
018
019import static javax.ws.rs.core.Response.Status.OK;
020import static net.java.dev.webdav.jaxrs.xml.properties.ResourceType.COLLECTION;
021
022import java.net.URI;
023import java.util.ArrayList;
024import java.util.Date;
025import java.util.LinkedList;
026import java.util.List;
027
028import javax.servlet.http.HttpServletRequest;
029import javax.ws.rs.DELETE;
030import javax.ws.rs.GET;
031import javax.ws.rs.HEAD;
032import javax.ws.rs.HeaderParam;
033import javax.ws.rs.Produces;
034import javax.ws.rs.core.Context;
035import javax.ws.rs.core.Response;
036import javax.ws.rs.core.UriInfo;
037
038import net.java.dev.webdav.jaxrs.methods.COPY;
039import net.java.dev.webdav.jaxrs.methods.LOCK;
040import net.java.dev.webdav.jaxrs.methods.MKCOL;
041import net.java.dev.webdav.jaxrs.methods.MOVE;
042import net.java.dev.webdav.jaxrs.methods.PROPFIND;
043import net.java.dev.webdav.jaxrs.methods.PROPPATCH;
044import net.java.dev.webdav.jaxrs.methods.UNLOCK;
045import net.java.dev.webdav.jaxrs.xml.elements.ActiveLock;
046import net.java.dev.webdav.jaxrs.xml.elements.Depth;
047import net.java.dev.webdav.jaxrs.xml.elements.HRef;
048import net.java.dev.webdav.jaxrs.xml.elements.LockRoot;
049import net.java.dev.webdav.jaxrs.xml.elements.LockScope;
050import net.java.dev.webdav.jaxrs.xml.elements.LockToken;
051import net.java.dev.webdav.jaxrs.xml.elements.LockType;
052import net.java.dev.webdav.jaxrs.xml.elements.MultiStatus;
053import net.java.dev.webdav.jaxrs.xml.elements.Owner;
054import net.java.dev.webdav.jaxrs.xml.elements.Prop;
055import net.java.dev.webdav.jaxrs.xml.elements.PropStat;
056import net.java.dev.webdav.jaxrs.xml.elements.Status;
057import net.java.dev.webdav.jaxrs.xml.elements.TimeOut;
058import net.java.dev.webdav.jaxrs.xml.properties.CreationDate;
059import net.java.dev.webdav.jaxrs.xml.properties.DisplayName;
060import net.java.dev.webdav.jaxrs.xml.properties.GetContentLength;
061import net.java.dev.webdav.jaxrs.xml.properties.GetContentType;
062import net.java.dev.webdav.jaxrs.xml.properties.GetLastModified;
063import net.java.dev.webdav.jaxrs.xml.properties.LockDiscovery;
064import net.java.dev.webdav.jaxrs.xml.properties.SupportedLock;
065
066import org.apache.commons.lang.StringEscapeUtils;
067import org.nuxeo.ecm.webdav.jaxrs.IsCollection;
068import org.nuxeo.ecm.webdav.jaxrs.IsFolder;
069import org.nuxeo.ecm.webdav.jaxrs.IsHidden;
070
071public class VirtualFolderResource extends AbstractResource {
072
073    private LinkedList<String> rootFolderNames;
074
075    public VirtualFolderResource(String path, HttpServletRequest request, LinkedList<String> rootFolderNames) {
076        super(path, request);
077        this.rootFolderNames = rootFolderNames;
078    }
079
080    @GET
081    @Produces("text/html")
082    public String get() {
083        StringBuilder sb = new StringBuilder();
084        sb.append("<html><body><p>");
085        sb.append("Folder listing for ");
086        sb.append(path);
087        sb.append("/");
088        sb.append("</p>\n<ul>\n");
089        for (String name : rootFolderNames) {
090            String qname = StringEscapeUtils.escapeHtml(name);
091            sb.append("<li><a href=\"");
092            sb.append(qname);
093            sb.append("/"); // terminating slash
094            sb.append("\">");
095            sb.append(qname);
096            sb.append("</a></li>\n");
097        }
098        sb.append("</ul></body>\n");
099        return sb.toString();
100    }
101
102    @PROPFIND
103    public Response propfind(@Context UriInfo uriInfo, @HeaderParam("depth") String depth) {
104
105        if (depth == null) {
106            depth = "1";
107        }
108
109        Date lastModified = new Date();
110        Date creationDate = new Date();
111
112        @SuppressWarnings("deprecation")
113        final net.java.dev.webdav.jaxrs.xml.elements.Response response = new net.java.dev.webdav.jaxrs.xml.elements.Response(
114                new HRef(uriInfo.getRequestUri()), null, null, null, new PropStat(new Prop(new DisplayName("nuxeo"), /*
115                                                                                                                      * @
116                                                                                                                      * TODO
117                                                                                                                      * :
118                                                                                                                      * fix
119                                                                                                                      * this
120                                                                                                                      * .
121                                                                                                                      * Hardcoded
122                                                                                                                      * root
123                                                                                                                      * name
124                                                                                                                      */
125                new LockDiscovery(), new SupportedLock(), new IsFolder("t"), new IsCollection(Integer.valueOf(1)),
126                        new IsHidden(Integer.valueOf(0)), new GetContentType("application/octet-stream"),
127                        new GetContentLength(0), new CreationDate(creationDate), new GetLastModified(lastModified),
128                        COLLECTION), new Status(OK)));
129
130        if (depth.equals("0")) {
131            return Response.status(207).entity(new MultiStatus(response)).build();
132        }
133
134        List<net.java.dev.webdav.jaxrs.xml.elements.Response> responses = new ArrayList<net.java.dev.webdav.jaxrs.xml.elements.Response>();
135        responses.add(response);
136
137        for (String name : rootFolderNames) {
138            lastModified = new Date();
139            creationDate = new Date();
140            PropStatBuilderExt props = new PropStatBuilderExt();
141            props.lastModified(lastModified).creationDate(creationDate).displayName(name).status(OK);
142            props.isCollection();
143
144            PropStat found = props.build();
145
146            net.java.dev.webdav.jaxrs.xml.elements.Response childResponse;
147            URI childUri = uriInfo.getRequestUriBuilder().path(name).build();
148
149            childResponse = new net.java.dev.webdav.jaxrs.xml.elements.Response(new HRef(childUri), null, null, null,
150                    found);
151
152            responses.add(childResponse);
153        }
154
155        MultiStatus st = new MultiStatus(
156                responses.toArray(new net.java.dev.webdav.jaxrs.xml.elements.Response[responses.size()]));
157        return Response.status(207).entity(st).build();
158    }
159
160    @DELETE
161    public Response delete() {
162        return Response.status(401).build();
163    }
164
165    @COPY
166    public Response copy() {
167        return Response.status(401).build();
168    }
169
170    @MOVE
171    public Response move() {
172        return Response.status(401).build();
173    }
174
175    @PROPPATCH
176    public Response proppatch() {
177        return Response.status(401).build();
178    }
179
180    @MKCOL
181    public Response mkcol() {
182        return Response.status(405).build();
183    }
184
185    @HEAD
186    public Response head() {
187        return Response.status(404).build();
188    }
189
190    @LOCK
191    public Response lock(@Context UriInfo uriInfo) {
192        Prop prop = new Prop(new LockDiscovery(new ActiveLock(LockScope.EXCLUSIVE, LockType.WRITE, Depth.ZERO,
193                new Owner("Administrator"), new TimeOut(10000L), new LockToken(new HRef("urn:uuid:Administrator")),
194                new LockRoot(new HRef(uriInfo.getRequestUri())))));
195
196        return Response.ok().entity(prop).header("Lock-Token", "urn:uuid:Administrator").build();
197    }
198
199    @UNLOCK
200    public Response unlock() {
201        return Response.status(204).build();
202    }
203
204}