Package org.geoserver.flow.config

Source Code of org.geoserver.flow.config.DefaultControlFlowConfigurator$RateControllerBuilder

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.flow.config;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.geoserver.flow.ControlFlowConfigurator;
import org.geoserver.flow.FlowController;
import org.geoserver.flow.controller.BasicOWSController;
import org.geoserver.flow.controller.CookieKeyGenerator;
import org.geoserver.flow.controller.GlobalFlowController;
import org.geoserver.flow.controller.IpFlowController;
import org.geoserver.flow.controller.IpKeyGenerator;
import org.geoserver.flow.controller.KeyGenerator;
import org.geoserver.flow.controller.OWSRequestMatcher;
import org.geoserver.flow.controller.RateFlowController;
import org.geoserver.flow.controller.SingleIpFlowController;
import org.geoserver.flow.controller.UserConcurrentFlowController;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.GeoServerResourceLoader;
import org.geoserver.platform.resource.Resource;
import org.geoserver.security.PropertyFileWatcher;
import org.geotools.util.logging.Logging;

/**
* Basic property file based {@link ControlFlowConfigurator} implementation
*
* @author Andrea Aime - OpenGeo
* @author Juan Marin, OpenGeo
*/
public class DefaultControlFlowConfigurator implements ControlFlowConfigurator {
    static final Pattern RATE_PATTERN = Pattern.compile("(\\d+)/([smhd])(;(\\d+)s)?");

    static final Logger LOGGER = Logging.getLogger(DefaultControlFlowConfigurator.class);
    static final String PROPERTYFILENAME="controlflow.properties";

    /**
     * Factors out the code to build a rate flow controller
     *
     * @author Andrea Aime - GeoSolutions
     *
     */
    static abstract class RateControllerBuilder {
        public FlowController build(String[] keys, String value) {
            Matcher matcher = RATE_PATTERN.matcher(value);
            if (!matcher.matches()) {
                LOGGER.severe("Rate limiting rule values should be expressed as <rate</<unit>[;<delay>s], "
                        + "where unit can be s, m, h or d. This one is invalid: "
                        + value);
                return null;
            }
            int rate = Integer.parseInt(matcher.group(1));
            long interval = Intervals.valueOf(matcher.group(2)).duration;
            int delay = 0;
            String userDelay = matcher.group(4);
            if (userDelay != null) {
                delay = Integer.parseInt(userDelay) * 1000;
            }
           
            String service = keys.length >= 3 ? keys[2] : null;
            String request = keys.length >= 4 ? keys[3] : null;
            String format = keys.length >= 5 ? keys[4] : null;
            OWSRequestMatcher requestMatcher = new OWSRequestMatcher(service, request, format);
            KeyGenerator keyGenerator = buildKeyGenerator(keys, value);
            return new RateFlowController(requestMatcher, rate, interval, delay, keyGenerator);
        }

        protected abstract KeyGenerator buildKeyGenerator(String[] keys, String value);
    }
    PropertyFileWatcher configFile;

    long timeout = -1;

    /** Default watches controlflow.properties */
    public DefaultControlFlowConfigurator() {
        GeoServerResourceLoader loader = GeoServerExtensions.bean(GeoServerResourceLoader.class);
        Resource controlflow = loader.get(PROPERTYFILENAME);
        configFile = new PropertyFileWatcher(controlflow);       
    }

    /**
     * Constructor used for testing purposes
     *
     * @param watcher
     */
    DefaultControlFlowConfigurator(PropertyFileWatcher watcher) {
        this.configFile = watcher;
    }

    public List<FlowController> buildFlowControllers() throws Exception {
        timeout = -1;

        Properties p = configFile.getProperties();
        List<FlowController> newControllers = new ArrayList<FlowController>();
        for (Object okey : p.keySet()) {
            String key = ((String) okey).trim();
            String value = (String) p.get(okey);
            LOGGER.info("Loading control-flow configuration: " + key + "=" + value);

            String[] keys = key.split("\\s*\\.\\s*");

            int queueSize = 0;
            StringTokenizer tokenizer = new StringTokenizer(value, ",");
            try {
                // some properties are not integers
                if("ip.blacklist".equals(key) && "ip.whitelist".equals(key)) {
                    continue;
                } else {
                    if (!key.startsWith("user.ows") && !key.startsWith("ip.ows")) {
                        if (tokenizer.countTokens() == 1) {
                            queueSize = Integer.parseInt(value);
                        } else {
                            queueSize = Integer.parseInt(tokenizer.nextToken());
                        }
                    }
                }
            } catch (NumberFormatException e) {
                LOGGER.severe("Rules should be assigned just a queue size, instead " + key
                        + " is associated to " + value);
                continue;
            }

            FlowController controller = null;
            if ("timeout".equalsIgnoreCase(key)) {
                timeout = queueSize * 1000;
                continue;
            }
            if ("ows.global".equalsIgnoreCase(key)) {
                controller = new GlobalFlowController(queueSize);
            } else if ("ows".equals(keys[0])) {
                // todo: check, if possible, if the service, method and output format actually exist
                if (keys.length >= 4) {
                    controller = new BasicOWSController(keys[1], keys[2], keys[3], queueSize);
                } else if (keys.length == 3) {
                    controller = new BasicOWSController(keys[1], keys[2], queueSize);
                } else if (keys.length == 2) {
                    controller = new BasicOWSController(keys[1], queueSize);
                }
            } else if ("user".equals(keys[0])) {
                if (keys.length == 1) {
                    controller = new UserConcurrentFlowController(queueSize);
                } else if ("ows".equals(keys[1])) {
                    controller = new RateControllerBuilder() {

                        @Override
                        protected KeyGenerator buildKeyGenerator(String[] keys, String value) {
                            return new CookieKeyGenerator();
                        }

                    }.build(keys, value);
                }
            } else if ("ip".equals(keys[0])) {
                if (keys.length == 1) {
                    controller = new IpFlowController(queueSize);
                } else if (keys.length > 1 && "ows".equals(keys[1])) {
                    controller = new RateControllerBuilder() {

                        @Override
                        protected KeyGenerator buildKeyGenerator(String[] keys, String value) {
                            return new IpKeyGenerator();
                        }

                    }.build(keys, value);
                } else if (keys.length > 1) {
                  if(!"blacklist".equals(keys[1]) && !"whitelist".equals(keys[1])){
                    String ip = key.substring("ip.".length());
                    controller = new SingleIpFlowController(queueSize, ip);
                  }
                }
            }
            if (controller == null) {
                LOGGER.severe("Could not parse rule '" + okey + "=" + value);
            } else {
                newControllers.add(controller);
            }
        }

        return newControllers;
    }

    public boolean isStale() {
        return configFile.isStale();
    }

    public long getTimeout() {
        return timeout;
    }

}
TOP

Related Classes of org.geoserver.flow.config.DefaultControlFlowConfigurator$RateControllerBuilder

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.