001/*
002 * (C) Copyright 2006-2008 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 *     bstefanescu
016 *
017 * $Id$
018 */
019
020package org.nuxeo.ecm.webengine.model.impl;
021
022import java.io.IOException;
023import java.io.PrintWriter;
024import java.io.StringWriter;
025import java.util.Date;
026
027import javax.servlet.http.HttpServletRequest;
028import javax.ws.rs.GET;
029import javax.ws.rs.Path;
030import javax.ws.rs.PathParam;
031import javax.ws.rs.WebApplicationException;
032import javax.ws.rs.core.Context;
033import javax.ws.rs.core.HttpHeaders;
034import javax.ws.rs.core.Response;
035import javax.ws.rs.core.Response.ResponseBuilder;
036import javax.ws.rs.core.UriInfo;
037
038import org.nuxeo.ecm.core.api.DocumentModel;
039import org.nuxeo.ecm.webengine.WebException;
040import org.nuxeo.ecm.webengine.app.DefaultContext;
041import org.nuxeo.ecm.webengine.model.Module;
042import org.nuxeo.ecm.webengine.model.ModuleResource;
043import org.nuxeo.ecm.webengine.model.ResourceType;
044import org.nuxeo.ecm.webengine.model.WebContext;
045import org.nuxeo.ecm.webengine.model.WebObject;
046import org.nuxeo.ecm.webengine.scripting.ScriptFile;
047
048/**
049 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
050 */
051public class ModuleRoot extends DefaultObject implements ModuleResource {
052
053    protected HttpServletRequest request;
054
055    protected UriInfo uriInfo;
056
057    protected HttpHeaders httpHeaders;
058
059    @Context
060    public void setUriInfo(UriInfo info) {
061        this.uriInfo = info;
062        if (request != null && httpHeaders != null) {
063            init();
064        }
065    }
066
067    @Context
068    public void setHttpHeaders(HttpHeaders headers) {
069        this.httpHeaders = headers;
070        if (request != null && uriInfo != null) {
071            init();
072        }
073    }
074
075    @Context
076    public void setHttpRequest(HttpServletRequest request) {
077        this.request = request;
078        if (uriInfo != null && httpHeaders != null) {
079            init();
080        }
081    }
082
083    private void init() {
084        DefaultContext ctx = (DefaultContext) request.getAttribute(WebContext.class.getName());
085        if (ctx == null) {
086            throw new java.lang.IllegalStateException(
087                    "No WebContext found in http request! You should install the WebEngineFilter");
088        }
089        ctx.setHttpHeaders(httpHeaders);
090        ctx.setUriInfo(uriInfo);
091        Module module = findModule(ctx);
092        ResourceType type = module.getType(getClass().getAnnotation(WebObject.class).type());
093        ctx.setModule(module);
094        initialize(ctx, type);
095        setRoot(true);
096        ctx.push(this);
097    }
098
099    private Module findModule(DefaultContext ctx) {
100        Path path = getClass().getAnnotation(Path.class);
101        if (path == null) {
102            throw new java.lang.IllegalStateException("ModuleRoot not annotated with @Path: " + getClass());
103        }
104        ModuleConfiguration mc = ctx.getEngine().getModuleManager().getModuleByRootClass(getClass());
105        if (mc == null) {
106            throw new java.lang.IllegalStateException("No module found for root resource: " + getClass());
107        }
108        return mc.get();
109    }
110
111    @GET
112    @Path("skin/{path:.*}")
113    public Response getSkinResource(@PathParam("path") String path) {
114        try {
115            ScriptFile file = getModule().getSkinResource("/resources/" + path);
116            if (file != null) {
117                long lastModified = file.lastModified();
118                ResponseBuilder resp = Response.ok(file.getFile()).lastModified(new Date(lastModified)).header(
119                        "Cache-Control", "public").header("Server", "Nuxeo/WebEngine-1.0");
120
121                String mimeType = ctx.getEngine().getMimeType(file.getExtension());
122                if (mimeType == null) {
123                    mimeType = "text/plain";
124                }
125                resp.type(mimeType);
126                return resp.build();
127            }
128        } catch (IOException e) {
129            throw WebException.wrap("Failed to get resource file: " + path, e);
130        }
131        return Response.status(404).build();
132    }
133
134    /**
135     * You should override this method to resolve objects to links. This method is usually called by a search view to
136     * generate links for object that are listed
137     *
138     * @param doc the document
139     * @return the link corresponding to that object
140     */
141    public String getLink(DocumentModel doc) {
142        return new StringBuilder().append(getPath()).append("/@nxdoc/").append(doc.getId()).toString();
143    }
144
145    public Object handleError(WebApplicationException e) {
146        return e;
147    }
148
149}