Package com.tacitknowledge.flip.servlet

Source Code of com.tacitknowledge.flip.servlet.FlipOverrideFilter

/* Copyright 2012 Tacit Knowledge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.tacitknowledge.flip.servlet;

import java.io.IOException;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.google.common.base.Predicate;
import com.google.common.collect.Maps;
import com.tacitknowledge.flip.model.FeatureDescriptor;
import com.tacitknowledge.flip.model.FeatureState;
import com.tacitknowledge.flip.properties.FeatureDescriptorsMap;

/**
* Filter used to override a specific toggle for the current session.
* <p>
* To override a toggle, add the toggle override prefix ("flip" by default), followed by a period
* and the feature name, and set it to either 'enabled' or 'disabled'. For example, to turn off the
* "self-destruct" toggle, add "flip.self-destruct=disabled" to the URL.
* </p>
* <p>
* The override prefix can be set via the "request-param-prefix" init value. The default is "flip".
* </p>
*
* @author Serghei Soloviov <ssoloviov@tacitknowledge.com>
* @author Petric Coroli <pcoroli@tacitknowledge.com>
*/
public class FlipOverrideFilter implements Filter
{
    public static final String SESSION_FEATURES_KEY = "FLIP_SESSION_FEATURES";

    private static final String DEFAULT_REQUEST_PARAM_PREFIX = "flip.";

    private static final String REQUEST_PARAM_PREFIX_CONFIG_KEY = "request-param-prefix";

    private String requestParameterPrefix = DEFAULT_REQUEST_PARAM_PREFIX;

    public void init(final FilterConfig filterConfig) throws ServletException
    {
        String prefix = filterConfig.getInitParameter(REQUEST_PARAM_PREFIX_CONFIG_KEY);
        if (prefix != null && prefix.trim().length() > 0)
        {
            requestParameterPrefix = prefix.trim() + ".";
        }
    }

    /**
     * {@inheritDoc }
     */
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
        throws IOException, ServletException
    {
        applyFeaturesFromRequestParameters(request);

        chain.doFilter(request, response);
        FlipWebContext.clear();
    }

    /**
     * {@inheritDoc }
     */
    public void destroy()
    {

    }

    /**
     * The method which uses the request parameters and apply them into the session
     * attribute {@link #SESSION_FEATURES_KEY}. This session attribute holds the
     * map {@link FeatureDescriptorsMap}. The method do not creates the session. So
     * if the session do not exists then the request parameters will be ignored.
     * If in the session under key {@link #SESSION_FEATURES_KEY} persists the
     * object other than of type {@link FeatureDescriptorsMap} or there is
     * no object in the session then the new object will be created and stored there.
     *
     * @param request the request to process
     */
    private void applyFeaturesFromRequestParameters(final ServletRequest request)
    {
        final HttpServletRequest httpRequest = (HttpServletRequest) request;
        final HttpSession session = httpRequest.getSession(false);

        FeatureDescriptorsMap featureDescriptors;
        if (session != null)
        {
            featureDescriptors = getSafeSessionFeatures(session);
            session.setAttribute(SESSION_FEATURES_KEY, featureDescriptors);
        }
        else
        {
            featureDescriptors = new FeatureDescriptorsMap();
        }

        applyRequestFeaturesToFeatureDescriptorsMap(request, featureDescriptors);
        FlipWebContext.setFeatureDescriptors(featureDescriptors);
    }

    /**
     * Returns the {@link FeatureDescriptorsMap} object stored in the session
     * under {@link #SESSION_FEATURES_KEY} key. If there is no such object or the
     * object is of another type the new object will be created. It do not stores
     * the object into the session back.
     *
     * @param session the session object where to extract the {@link FeatureDescriptorsMap}
     * @return the {@link FeatureDescriptorsMap} stored in the session or new one created on other cases.
     */
    private FeatureDescriptorsMap getSafeSessionFeatures(final HttpSession session)
    {
        final Object sessionObject = session.getAttribute(SESSION_FEATURES_KEY);

        if (sessionObject != null && sessionObject instanceof FeatureDescriptorsMap)
        {
            return (FeatureDescriptorsMap) sessionObject;
        }

        return new FeatureDescriptorsMap();
    }

    /**
     * Moves the features descriptors generated on request parameters to the {@link FeatureDescriptorsMap}.
     *
     * @param request the request where to extract the request parameters.
     * @param featureDescriptors the {@link FeatureDescriptorsMap} where to store the {@link FeatureDescriptor} objects.
     */
    private void applyRequestFeaturesToFeatureDescriptorsMap(final ServletRequest request,
            final FeatureDescriptorsMap featureDescriptors)
    {
        final Map<String, FeatureDescriptor> transformedParamMap = Maps.transformEntries(request.getParameterMap(),
                new RequestParametersTransformer());
        final Map<String, FeatureDescriptor> parameterMap = Maps.filterEntries(transformedParamMap,
                new RequestParametersFilter());

        for (final FeatureDescriptor descriptor : parameterMap.values())
        {
            featureDescriptors.put(descriptor.getName(), descriptor);
        }
    }

    private class RequestParametersTransformer implements
            Maps.EntryTransformer<String, String[], FeatureDescriptor>
    {
        public FeatureDescriptor transformEntry(final String key, final String[] value)
        {
            if (value == null || value.length == 0)
            {
                return null;
            }

            try
            {
                final FeatureState state = FeatureState.valueOf(value[0].toUpperCase());

                final FeatureDescriptor featureDescriptor = new FeatureDescriptor();
                featureDescriptor.setName(key.replaceFirst("^" + Pattern.quote(requestParameterPrefix), ""));
                featureDescriptor.setState(state);
                return featureDescriptor;
            }
            catch (final IllegalArgumentException e)
            {
                return null;
            }
        }
    }

    private class RequestParametersFilter implements Predicate<Map.Entry<String, FeatureDescriptor>>
    {
        public boolean apply(final Map.Entry<String, FeatureDescriptor> input)
        {
            return input.getKey().startsWith(requestParameterPrefix) && input.getValue() != null;
        }
    }
}
TOP

Related Classes of com.tacitknowledge.flip.servlet.FlipOverrideFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.