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