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