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