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