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 static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
025
026import java.io.IOException;
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.core.Context;
034import javax.ws.rs.core.Response;
035import javax.ws.rs.core.Response.ResponseBuilder;
036
037import org.nuxeo.ecm.core.api.DocumentModel;
038import org.nuxeo.ecm.core.api.NuxeoException;
039import org.nuxeo.ecm.webengine.app.DefaultContext;
040import org.nuxeo.ecm.webengine.model.Module;
041import org.nuxeo.ecm.webengine.model.ModuleResource;
042import org.nuxeo.ecm.webengine.model.ResourceType;
043import org.nuxeo.ecm.webengine.model.WebContext;
044import org.nuxeo.ecm.webengine.model.WebObject;
045import org.nuxeo.ecm.webengine.scripting.ScriptFile;
046
047import com.sun.jersey.api.core.HttpContext;
048import com.sun.jersey.server.impl.inject.ServerInjectableProviderContext;
049
050/**
051 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
052 */
053public class ModuleRoot extends DefaultObject implements ModuleResource {
054
055    @Context
056    protected HttpServletRequest request;
057
058    @Context
059    protected ServerInjectableProviderContext sic;
060
061    @Context
062    public void setContext(HttpContext hc) {
063        DefaultContext ctx = (DefaultContext) request.getAttribute(WebContext.class.getName());
064        if (ctx == null) {
065            throw new java.lang.IllegalStateException(
066                    "No WebContext found in http request! You should install the WebEngineFilter");
067        }
068        if (ctx.getModule() != null) { // just a resource, not a module root
069            return;
070        }
071        try {
072            ctx.setJerseyContext(sic, hc);
073            Module module = findModule(ctx);
074            ResourceType type = module.getType(getClass().getAnnotation(WebObject.class).type());
075            ctx.setModule(module);
076            initialize(ctx, type);
077            setRoot(true);
078        } finally {
079            ctx.push(this);
080        }
081    }
082
083    private Module findModule(DefaultContext ctx) {
084        Path path = getClass().getAnnotation(Path.class);
085        if (path == null) {
086            throw new java.lang.IllegalStateException("ModuleRoot not annotated with @Path: " + getClass());
087        }
088        ModuleConfiguration mc = ctx.getEngine().getModuleManager().getModuleByRootClass(getClass());
089        if (mc == null) {
090            throw new java.lang.IllegalStateException("No module found for root resource: " + getClass());
091        }
092        return mc.get(ctx);
093    }
094
095    @GET
096    @Path("skin/{path:.*}")
097    public Response getSkinResource(@PathParam("path") String path) {
098        try {
099            ScriptFile file = getModule().getSkinResource("/resources/" + path);
100            if (file != null) {
101                long lastModified = file.lastModified();
102                ResponseBuilder resp = Response.ok(file.getFile())
103                                               .lastModified(new Date(lastModified))
104                                               .header("Cache-Control", "public")
105                                               .header("Server", "Nuxeo/WebEngine-1.0");
106
107                String mimeType = ctx.getEngine().getMimeType(file.getExtension());
108                if (mimeType == null) {
109                    mimeType = "text/plain";
110                }
111                resp.type(mimeType);
112                return resp.build();
113            }
114        } catch (IOException e) {
115            throw new NuxeoException("Failed to get resource file: " + path, e);
116        }
117        return Response.status(SC_NOT_FOUND).build();
118    }
119
120    /**
121     * You should override this method to resolve objects to links. This method is usually called by a search view to
122     * generate links for object that are listed
123     *
124     * @param doc the document
125     * @return the link corresponding to that object
126     */
127    @Override
128    public String getLink(DocumentModel doc) {
129        return new StringBuilder().append(getPath()).append("/@nxdoc/").append(doc.getId()).toString();
130    }
131
132    @Override
133    public Object handleError(Throwable t) {
134        return t;
135    }
136}