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.text.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.escapeHtml4(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    @Produces({ "application/xml", "text/xml" })
106    public Response propfind(@Context UriInfo uriInfo, @HeaderParam("depth") String depth) {
107
108        if (depth == null) {
109            depth = "1";
110        }
111
112        Date lastModified = new Date();
113        Date creationDate = new Date();
114
115        @SuppressWarnings("deprecation")
116        final net.java.dev.webdav.jaxrs.xml.elements.Response response = new net.java.dev.webdav.jaxrs.xml.elements.Response(
117                new HRef(uriInfo.getRequestUri()), null, null, null, new PropStat(new Prop(new DisplayName("nuxeo"), /*
118                                                                                                                      * @
119                                                                                                                      * TODO
120                                                                                                                      * :
121                                                                                                                      * fix
122                                                                                                                      * this
123                                                                                                                      * .
124                                                                                                                      * Hardcoded
125                                                                                                                      * root
126                                                                                                                      * name
127                                                                                                                      */
128                new LockDiscovery(), new SupportedLock(), new IsFolder("t"), new IsCollection(Integer.valueOf(1)),
129                        new IsHidden(Integer.valueOf(0)), new GetContentType("application/octet-stream"),
130                        new GetContentLength(0), new CreationDate(creationDate), new GetLastModified(lastModified),
131                        COLLECTION), new Status(OK)));
132
133        if (depth.equals("0")) {
134            return Response.status(207).entity(new MultiStatus(response)).build();
135        }
136
137        List<net.java.dev.webdav.jaxrs.xml.elements.Response> responses = new ArrayList<net.java.dev.webdav.jaxrs.xml.elements.Response>();
138        responses.add(response);
139
140        for (String name : rootFolderNames) {
141            lastModified = new Date();
142            creationDate = new Date();
143            PropStatBuilderExt props = new PropStatBuilderExt();
144            props.lastModified(lastModified).creationDate(creationDate).displayName(name).status(OK);
145            props.isCollection();
146
147            PropStat found = props.build();
148
149            net.java.dev.webdav.jaxrs.xml.elements.Response childResponse;
150            URI childUri = uriInfo.getRequestUriBuilder().path(name).build();
151
152            childResponse = new net.java.dev.webdav.jaxrs.xml.elements.Response(new HRef(childUri), null, null, null,
153                    found);
154
155            responses.add(childResponse);
156        }
157
158        MultiStatus st = new MultiStatus(
159                responses.toArray(new net.java.dev.webdav.jaxrs.xml.elements.Response[responses.size()]));
160        return Response.status(207).entity(st).build();
161    }
162
163    @DELETE
164    public Response delete() {
165        return Response.status(401).build();
166    }
167
168    @COPY
169    public Response copy() {
170        return Response.status(401).build();
171    }
172
173    @MOVE
174    public Response move() {
175        return Response.status(401).build();
176    }
177
178    @PROPPATCH
179    public Response proppatch() {
180        return Response.status(401).build();
181    }
182
183    @MKCOL
184    public Response mkcol() {
185        return Response.status(405).build();
186    }
187
188    @HEAD
189    public Response head() {
190        return Response.status(404).build();
191    }
192
193    @LOCK
194    @Produces({ "application/xml", "text/xml" })
195    public Response lock(@Context UriInfo uriInfo) {
196        Prop prop = new Prop(new LockDiscovery(new ActiveLock(LockScope.EXCLUSIVE, LockType.WRITE, Depth.ZERO,
197                new Owner("Administrator"), new TimeOut(10000L), new LockToken(new HRef("urn:uuid:Administrator")),
198                new LockRoot(new HRef(uriInfo.getRequestUri())))));
199
200        return Response.ok().entity(prop).header("Lock-Token", "urn:uuid:Administrator").build();
201    }
202
203    @UNLOCK
204    @Produces({ "application/xml", "text/xml" })
205    public Response unlock() {
206        return Response.status(204).build();
207    }
208
209}