Package com.asakusafw.yaess.jobqueue

Source Code of com.asakusafw.yaess.jobqueue.JobClientProfile

/**
* Copyright 2011-2014 Asakusa Framework Team.
*
* 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.asakusafw.yaess.jobqueue;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.asakusafw.yaess.core.ExecutionScriptHandler;
import com.asakusafw.yaess.core.ServiceProfile;
import com.asakusafw.yaess.core.util.PropertiesUtil;
import com.asakusafw.yaess.jobqueue.client.HttpJobClient;
import com.asakusafw.yaess.jobqueue.client.JobClient;

/**
* A structured profile for {@link QueueHadoopScriptHandler}.
* @since 0.2.6
*/
public class JobClientProfile {

    static final Logger LOG = LoggerFactory.getLogger(JobClientProfile.class);

    static final String KEY_TIMEOUT = "timeout";

    static final String KEY_POLLING_INTERVAL = "pollingInterval";

    static final Pattern PATTERN_COMPONENT = Pattern.compile("\\d+");

    static final String KEY_URL = "url";

    static final String KEY_USER = "user";

    static final String KEY_PASSWORD = "password";

    static final long DEFAULT_TIMEOUT = 10000;

    static final long DEFAULT_POLLING_INTERVAL = 1000;

    private final String prefix;

    private final List<JobClient> clients;

    private final long timeout;

    private final long pollingInterval;

    /**
     * Creates a new instance.
     * @param prefix the profile namespace
     * @param clients clients
     * @param timeout timeout duration (ms)
     * @param pollingInterval polling interval (ms)
     * @throws IllegalArgumentException if some parameters were {@code null}
     */
    public JobClientProfile(String prefix, List<? extends JobClient> clients, long timeout, long pollingInterval) {
        if (prefix == null) {
            throw new IllegalArgumentException("prefix must not be null"); //$NON-NLS-1$
        }
        if (clients == null) {
            throw new IllegalArgumentException("clients must not be null"); //$NON-NLS-1$
        }
        if (clients.isEmpty()) {
            throw new IllegalArgumentException("clients must not be empty"); //$NON-NLS-1$
        }
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout must be >= 0"); //$NON-NLS-1$
        }
        if (pollingInterval <= 0) {
            throw new IllegalArgumentException("pollingInterval must be >= 0"); //$NON-NLS-1$
        }
        this.prefix = prefix;
        this.clients = Collections.unmodifiableList(new ArrayList<JobClient>(clients));
        this.timeout = timeout;
        this.pollingInterval = pollingInterval;
    }

    /**
     * Returns the current namespace.
     * @return the prefix
     */
    public String getPrefix() {
        return prefix;
    }

    /**
     * Returns the job clients.
     * @return the clients
     */
    public List<JobClient> getClients() {
        return clients;
    }

    /**
     * Returns the timeout duration.
     * @return the timeout (ms)
     */
    public long getTimeout() {
        return timeout;
    }

    /**
     * Returns the polling interval.
     * @return the polling interval (ms)
     */
    public long getPollingInterval() {
        return pollingInterval;
    }

    /**
     * Converts general profile into the corresponded this profile.
     * @param profile general profile
     * @return this profile
     * @throws IllegalArgumentException if some parameters were {@code null}
     */
    public static JobClientProfile convert(ServiceProfile<?> profile) {
        if (profile == null) {
            throw new IllegalArgumentException("profile must not be null"); //$NON-NLS-1$
        }
        Map<String, String> conf = new HashMap<String, String>(profile.getConfiguration());
        conf.remove(ExecutionScriptHandler.KEY_RESOURCE);
        removeKeyPrefix(conf, ExecutionScriptHandler.KEY_PROP_PREFIX);
        long timeout = extractLong(profile, conf, KEY_TIMEOUT, DEFAULT_TIMEOUT);
        if (timeout <= 0) {
            throw new IllegalArgumentException(MessageFormat.format(
                    "Request time out must be > 0 ({0}.{1}={2})",
                    profile.getPrefix(),
                    KEY_TIMEOUT,
                    timeout));
        }
        long pollingInterval = extractLong(profile, conf, KEY_POLLING_INTERVAL, DEFAULT_POLLING_INTERVAL);
        if (pollingInterval <= 0) {
            throw new IllegalArgumentException(MessageFormat.format(
                    "Status polling interval must be > 0 ({0}.{1}={2})",
                    profile.getPrefix(),
                    KEY_TIMEOUT,
                    pollingInterval));
        }
        List<JobClient> clients = extractClients(profile, conf);
        if (clients.isEmpty()) {
            throw new IllegalArgumentException(MessageFormat.format(
                    "There must be one or more job clients ({0}.<n>)",
                    profile.getPrefix()));
        }
        return new JobClientProfile(profile.getPrefix(), clients, timeout, pollingInterval);
    }

    private static long extractLong(
            ServiceProfile<?> profile,
            Map<String, String> conf,
            String key,
            long defaultValue) {
        assert profile != null;
        assert conf != null;
        assert key != null;
        String value = profile.normalize(key, conf.remove(key), false, true);
        if (value == null) {
            return defaultValue;
        }
        try {
            return Long.parseLong(value);
        } catch (RuntimeException e) {
            throw new IllegalArgumentException(MessageFormat.format(
                    "{0}.{1} must be an integer ({2})",
                    profile.getPrefix(),
                    key,
                    value));
        }
    }

    private static List<JobClient> extractClients(
            ServiceProfile<?> profile,
            Map<String, String> conf) {
        assert profile != null;
        Set<String> keys = PropertiesUtil.getChildKeys(conf, "", ".");
        Map<Integer, JobClient> results = new TreeMap<Integer, JobClient>();
        for (String key : keys) {
            if (isClientPrefix(key) == false) {
                throw new IllegalArgumentException(MessageFormat.format(
                        "Unknown profile: {0}.{1}",
                        profile.getPrefix(),
                        key));
            }
            int number = Integer.parseInt(key);
            Map<String, String> subconf = PropertiesUtil.createPrefixMap(conf, key + ".");
            String prefix = profile.getPrefix() + "." + key;
            String url = resolve(profile, subconf, prefix, KEY_URL);
            if (url == null) {
                throw new IllegalArgumentException(MessageFormat.format(
                        "Target URL is not specified: {0}.{1}",
                        prefix,
                        KEY_URL));
            }
            String user = resolve(profile, subconf, prefix, KEY_USER);
            String password = resolve(profile, subconf, prefix, KEY_PASSWORD);
            if (user == null || user.isEmpty()) {
                results.put(number, new HttpJobClient(url));
            } else {
                password = password == null ? "" : password;
                results.put(number, new HttpJobClient(url, user, password));
            }
        }
        return new ArrayList<JobClient>(results.values());
    }

    private static String resolve(
            ServiceProfile<?> profile,
            Map<String, String> conf,
            String prefix,
            String key) {
        assert profile != null;
        assert conf != null;
        assert prefix != null;
        assert key != null;
        String value = conf.get(key);
        if (value == null) {
            return null;
        }
        return resolve(profile, prefix + "." + key, value);
    }

    private static String resolve(ServiceProfile<?> profile, String key, String value) {
        assert profile != null;
        assert key != null;
        assert value != null;
        try {
            return profile.getContext().getContextParameters().replace(value, true);
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(MessageFormat.format(
                    "Failed to resolve {0} ({1})",
                    key,
                    value), e);
        }
    }

    private static boolean isClientPrefix(String key) {
        assert key != null;
        return PATTERN_COMPONENT.matcher(key).matches();
    }

    private static void removeKeyPrefix(Map<?, ?> properties, String prefix) {
        assert properties != null;
        assert prefix != null;
        for (Iterator<?> iter = properties.keySet().iterator(); iter.hasNext();) {
            Object key = iter.next();
            if ((key instanceof String) == false) {
                continue;
            }
            String name = (String) key;
            if (name.startsWith(prefix)) {
                iter.remove();
            }
        }
    }
}
TOP

Related Classes of com.asakusafw.yaess.jobqueue.JobClientProfile

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.