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