class FastCGIHandlerFactory {

    public static FastCGIHandler create(final Map<String, String> config) {
        final FastCGIHandler handler = new FastCGIHandler();
        if (config.get(PARAM_SERVER_ADDRESS) != null) {
            getLog().info(
                    "configuring fastcgi servlet using default single connection handler");
            handler.setConnectionFactory(new SingleConnectionFactory(config
                    .get(PARAM_SERVER_ADDRESS)));
        }
        else if (config.get(PARAM_CONNECTION_FACTORY) != null) {
            final String className = config.get(PARAM_CONNECTION_FACTORY)
                    .trim();
            getLog().info(
                    "configuring fastCGI handler using custom class '"
                            + className + "'");
            handler.setConnectionFactory(buildConnectionFactoryForClass(className));
        }
        else if (config.get(PARAM_CLUSTER_ADRESSES) != null) {
            getLog().info(
                    "configuring fastCGI handler using the following adresses : ");
            final PoolFactory poolFactory = PoolFactoryFactory
                    .getOrCreatePoolFactory();
            for (final String addr : config.get(PARAM_CLUSTER_ADRESSES)
                    .replaceAll("[\n\t]", ";").replaceAll(" ", "").split(";")) {
                if (!addr.isEmpty()) {
                    getLog().info("  => " + addr);
                    poolFactory.addAddress(addr.trim());
                }
            }
            handler.setConnectionFactory(new PooledConnectionFactory(
                    poolFactory));// sorry for the confusion, everything seems
            // to be named 'factory'...
        }
        else {
            throw new IllegalArgumentException(
                    "Cannot create fcgi handler : did you provide any configuration ?");
        }

        // handle filtered-headers param
        if (config.get(PARAM_ALLOWED_HEADERS) != null) {
            final String allowedHeaders = config.get(PARAM_ALLOWED_HEADERS);

            if (getLog().isInfoEnabled()) {
                getLog().info(
                        "The following http headers will be transmitted (regex): ["
                                + allowedHeaders + "]");
            }
            Pattern allowedHeadersPattern;
            try {
                allowedHeadersPattern = Pattern.compile(allowedHeaders);
            }
            catch (PatternSyntaxException pse) {
                throw new IllegalArgumentException(
                        "Invalid regular expression in configuration parameter "
                        + PARAM_ALLOWED_HEADERS, pse);
            }
            handler.setAllowedHeaders(allowedHeadersPattern);
        }

        if (config.get(PARAM_PHP_SCRIPT_FROM_PATH) != null) {
            final String phpScriptFromPathPattern = config.get(PARAM_PHP_SCRIPT_FROM_PATH);

            Pattern phpScriptFromPath;
            try {
                phpScriptFromPath = Pattern.compile(phpScriptFromPathPattern);
            }
            catch (PatternSyntaxException pse) {
                throw new IllegalArgumentException(
                        "Invalid regular expression in configuration parameter "
                        + PARAM_PHP_SCRIPT_FROM_PATH, pse);
            }
            handler.setPhpScriptFromPathPattern(phpScriptFromPath);
        }

        if (config.get(PARAM_KEEP_ALIVE) != null) {
            final String value = config.get(PARAM_KEEP_ALIVE);
            if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes")) {
                handler.setKeepAlive(true);
            }
        }

        if (config.get(PARAM_START_EXECUTABLE) != null) {
            final String cmd = config.get(PARAM_START_EXECUTABLE);
            try {
                handler.startProcess(cmd);
            }
            catch (final IOException e) {
                getLog().error("while starting external process", e);
                throw new RuntimeException(e);
            }
        }

        return handler;
    }

}