001/*
002 * (C) Copyright 2015 Nuxeo SA (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-2.1.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 *     Nicolas Chapurlat <nchapurlat@nuxeo.com>
016 */
017
018package org.nuxeo.ecm.webengine.jaxrs.coreiodelegate;
019
020import java.util.Enumeration;
021import java.util.Map;
022
023import javax.servlet.ServletRequest;
024import javax.servlet.http.HttpServletRequest;
025
026import org.nuxeo.ecm.core.api.CoreSession;
027import org.nuxeo.ecm.core.io.registry.context.RenderingContext;
028import org.nuxeo.ecm.core.io.registry.context.RenderingContext.CtxBuilder;
029import org.nuxeo.ecm.core.io.registry.context.RenderingContextImpl.RenderingContextBuilder;
030import org.nuxeo.ecm.webengine.jaxrs.session.SessionFactory;
031
032/**
033 * Utility class that get or create a {@link RenderingContext} from the current {@link HttpServletRequest}.
034 *
035 * @since 7.2
036 */
037public final class RenderingContextWebUtils {
038
039    private static final String CTX_KEY = "_STORED_GENERATED_RENDERING_CONTEXT";
040
041    public static final String REQUEST_KEY = "_STORED_GENERATED_HTTP_SERVLET_REQUEST";
042
043    private RenderingContextWebUtils() {
044    }
045
046    /**
047     * Get the current context in the current {@link HttpServletRequest} or create it from the current
048     * {@link HttpServletRequest}.
049     *
050     * @since 7.2
051     */
052    public static RenderingContext getContext(ServletRequest request) {
053        // try to get an existing RenderingContext from the request
054        Object stored = request.getAttribute(getContextKey());
055        if (stored != null) {
056            return (RenderingContext) stored;
057        }
058        RenderingContextBuilder builder = CtxBuilder.builder();
059        fillContext(builder, request);
060        RenderingContext ctx = builder.get();
061        registerContext(request, ctx);
062        return ctx;
063    }
064
065    /**
066     * Register the given context as the context to use to manage the marshalling.
067     *
068     * @param request The current request.
069     * @param ctx The context to register.
070     * @since 7.10
071     */
072    public static void registerContext(ServletRequest request, RenderingContext ctx) {
073        request.setAttribute(getContextKey(), ctx);
074    }
075
076    /**
077     * Return the key used to store the context in the request.
078     *
079     * @since 7.10
080     */
081    public static String getContextKey() {
082        return CTX_KEY;
083    }
084
085    /**
086     * Create an {@link RenderingContextBuilder}, fill it with the current {@link HttpServletRequest} and return it.
087     *
088     * @since 7.2
089     */
090    public static RenderingContextBuilder getBuilder(ServletRequest request) {
091        RenderingContextBuilder builder = CtxBuilder.builder();
092        fillContext(builder, request);
093        return builder;
094    }
095
096    /**
097     * Fill an existing with the current {@link HttpServletRequest}.
098     *
099     * @since 7.2
100     */
101    public static RenderingContextBuilder fillContext(RenderingContextBuilder builder, ServletRequest request) {
102        // create a context builder and put base url, session and request
103        builder.param(REQUEST_KEY, request);
104        // for web context, put the base url, the session and the headers
105        if (request instanceof HttpServletRequest) {
106            HttpServletRequest webRequest = (HttpServletRequest) request;
107            // base url
108            @SuppressWarnings("deprecation")
109            String baseURL = VirtualHostHelper.getBaseURL(webRequest);
110            // current session
111            CoreSession session = SessionFactory.getSession(webRequest);
112            builder.base(baseURL).session(session);
113            // headers
114            Enumeration<String> headerNames = webRequest.getHeaderNames();
115            while (headerNames.hasMoreElements()) {
116                String headerName = headerNames.nextElement();
117                Enumeration<String> headerValues = webRequest.getHeaders(headerName);
118                while (headerValues.hasMoreElements()) {
119                    builder.param(headerName, headerValues.nextElement());
120                }
121            }
122        }
123        // parameters
124        for (Map.Entry<String, String[]> parameter : request.getParameterMap().entrySet()) {
125            builder.paramValues(parameter.getKey(), (Object[]) parameter.getValue());
126        }
127        // attributes
128        Enumeration<String> attributeNames = request.getAttributeNames();
129        while (attributeNames.hasMoreElements()) {
130            String attributeName = attributeNames.nextElement();
131            Object attributeValue = request.getAttribute(attributeName);
132            builder.param(attributeName, attributeValue);
133        }
134        return builder;
135    }
136
137}