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.net.URISyntaxException;
027import java.net.URLEncoder;
028
029import javax.servlet.http.HttpServletRequest;
030import javax.ws.rs.GET;
031import javax.ws.rs.PUT;
032import javax.ws.rs.core.Context;
033import javax.ws.rs.core.Response;
034import javax.ws.rs.core.UriInfo;
035import javax.xml.bind.JAXBException;
036import javax.xml.bind.Unmarshaller;
037
038import net.java.dev.webdav.jaxrs.methods.PROPFIND;
039import net.java.dev.webdav.jaxrs.xml.elements.HRef;
040import net.java.dev.webdav.jaxrs.xml.elements.LockEntry;
041import net.java.dev.webdav.jaxrs.xml.elements.LockScope;
042import net.java.dev.webdav.jaxrs.xml.elements.LockType;
043import net.java.dev.webdav.jaxrs.xml.elements.MultiStatus;
044import net.java.dev.webdav.jaxrs.xml.elements.Prop;
045import net.java.dev.webdav.jaxrs.xml.elements.PropFind;
046import net.java.dev.webdav.jaxrs.xml.elements.PropStat;
047import net.java.dev.webdav.jaxrs.xml.elements.Status;
048import net.java.dev.webdav.jaxrs.xml.properties.SupportedLock;
049
050import org.apache.commons.logging.Log;
051import org.apache.commons.logging.LogFactory;
052import org.nuxeo.ecm.core.api.Blob;
053import org.nuxeo.ecm.core.api.Blobs;
054import org.nuxeo.ecm.core.api.DocumentModel;
055import org.nuxeo.ecm.core.api.NuxeoException;
056import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
057import org.nuxeo.ecm.webdav.backend.Backend;
058import org.nuxeo.ecm.webdav.jaxrs.Util;
059
060/**
061 * Resource representing a file-like object in the repository. (I.e. not a folder).
062 */
063public class FileResource extends ExistingResource {
064
065    private static final Log log = LogFactory.getLog(FileResource.class);
066
067    public FileResource(String path, DocumentModel doc, HttpServletRequest request, Backend backend) {
068        super(path, doc, request, backend);
069    }
070
071    @GET
072    public Object get() {
073        Blob content = null;
074        BlobHolder bh = doc.getAdapter(BlobHolder.class);
075        if (bh != null) {
076            content = bh.getBlob();
077        }
078        if (content == null) {
079            return Response.ok("").build();
080        } else {
081            String mimeType = content.getMimeType();
082            if ("???".equals(mimeType)) {
083                mimeType = "application/octet-stream";
084            }
085            return Response.ok(content).type(mimeType).build();
086        }
087    }
088
089    @PUT
090    public Response put() {
091        if (backend.isLocked(doc.getRef()) && !backend.canUnlock(doc.getRef())) {
092            return Response.status(423).build();
093        }
094
095        try {
096            Blob content = Blobs.createBlob(request.getInputStream());
097            String contentType = request.getContentType();
098            if (contentType == null) {
099                contentType = "application/octet-stream";
100            }
101            content.setMimeType(contentType);
102            content.setFilename(name);
103
104            backend.updateDocument(doc, name, content);
105            try {
106                return Response.created(new URI(URLEncoder.encode(path, "UTF8"))).build();
107            } catch (URISyntaxException e) {
108                throw new NuxeoException(e);
109            }
110        } catch (IOException e) {
111            log.error("Error during PUT method execution", e);
112            return Response.status(409).build();
113        }
114    }
115
116    @PROPFIND
117    public Response propfind(@Context UriInfo uriInfo) throws IOException, JAXBException {
118
119        Unmarshaller u = Util.getUnmarshaller();
120
121        Prop prop = null;
122        if (request.getInputStream() != null && request.getContentLength() > 0) {
123            PropFind propFind;
124            try {
125                propFind = (PropFind) u.unmarshal(request.getInputStream());
126            } catch (JAXBException e) {
127                return Response.status(400).build();
128            }
129            prop = propFind.getProp();
130        }
131        // Util.printAsXml(prop);
132
133        PropStatBuilderExt props = getPropStatBuilderExt(doc, uriInfo);
134        PropStat propStatFound = props.build();
135        PropStat propStatNotFound = null;
136        if (prop != null) {
137            propStatNotFound = props.notFound(prop);
138        }
139
140        net.java.dev.webdav.jaxrs.xml.elements.Response response;
141        URI uri = uriInfo.getRequestUri();
142        PropStat filePropStat = new PropStat(new Prop(new SupportedLock(new LockEntry(LockScope.EXCLUSIVE,
143                LockType.WRITE))), new Status(OK));
144        if (doc.isLocked()) {
145            PropStat lockDiscoveryPropStat = new PropStat(new Prop(getLockDiscovery(doc, uriInfo)), new Status(OK));
146            if (propStatNotFound != null) {
147                response = new net.java.dev.webdav.jaxrs.xml.elements.Response(new HRef(uri), null, null, null,
148                        filePropStat, propStatFound, propStatNotFound, lockDiscoveryPropStat);
149            } else {
150                response = new net.java.dev.webdav.jaxrs.xml.elements.Response(new HRef(uri), null, null, null,
151                        filePropStat, propStatFound, lockDiscoveryPropStat);
152            }
153        } else {
154            if (propStatNotFound != null) {
155                response = new net.java.dev.webdav.jaxrs.xml.elements.Response(new HRef(uri), null, null, null,
156                        filePropStat, propStatFound, propStatNotFound);
157            } else {
158                response = new net.java.dev.webdav.jaxrs.xml.elements.Response(new HRef(uri), null, null, null,
159                        filePropStat, propStatFound);
160            }
161        }
162
163        MultiStatus st = new MultiStatus(response);
164        return Response.status(207).entity(st).build();
165    }
166
167}