| // Copyright 2012 Google Inc. All Rights Reserved. |
| // |
| // 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.google.gitiles; |
| |
| import com.google.common.base.Optional; |
| import com.google.common.base.Predicates; |
| import com.google.common.cache.CacheBuilder; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Iterables; |
| |
| import org.eclipse.jgit.lib.Config; |
| import org.joda.time.Duration; |
| |
| import java.util.TimeZone; |
| import java.util.concurrent.TimeUnit; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| /** Utilities for working with {@link Config} objects. */ |
| public class ConfigUtil { |
| /** |
| * Read a duration value from the configuration. |
| * <p> |
| * Durations can be written with unit suffixes, for example {@code "1 s"} or |
| * {@code "5 days"}. If units are not specified, milliseconds are assumed. |
| * |
| * @param config JGit config object. |
| * @param section section to read, e.g. "google" |
| * @param subsection subsection to read, e.g. "bigtable" |
| * @param name variable to read, e.g. "deadline". |
| * @param defaultValue value to use when the value is not assigned. |
| * @return a standard duration representing the time read, or defaultValue. |
| */ |
| public static Duration getDuration( |
| Config config, String section, String subsection, String name, Duration defaultValue) { |
| String valStr = config.getString(section, subsection, name); |
| if (valStr == null) { |
| return defaultValue; |
| } |
| valStr = valStr.trim(); |
| if (valStr.isEmpty()) { |
| return defaultValue; |
| } |
| Duration val = parseDuration(valStr); |
| if (val == null) { |
| String key = section + (subsection != null ? "." + subsection : "") + "." + name; |
| throw new IllegalStateException("Not time unit: " + key + " = " + valStr); |
| } |
| return val; |
| } |
| |
| /** |
| * Parse a duration value from a string. |
| * <p> |
| * Durations can be written with unit suffixes, for example {@code "1 s"} or |
| * {@code "5 days"}. If units are not specified, milliseconds are assumed. |
| * |
| * @param valStr the value to parse. |
| * @return a standard duration representing the time parsed, or null if not a |
| * valid duration. |
| */ |
| public static Duration parseDuration(String valStr) { |
| if (valStr == null) { |
| return null; |
| } |
| valStr = valStr.trim(); |
| if (valStr.isEmpty()) { |
| return null; |
| } |
| Matcher m = matcher("^([1-9][0-9]*(?:\\.[0-9]*)?)\\s*(.*)$", valStr); |
| if (!m.matches()) { |
| return null; |
| } |
| |
| String digits = m.group(1); |
| String unitName = m.group(2).trim(); |
| |
| TimeUnit unit; |
| if ("".equals(unitName)) { |
| unit = TimeUnit.MILLISECONDS; |
| } else if (anyOf(unitName, "ms", "millis", "millisecond", "milliseconds")) { |
| unit = TimeUnit.MILLISECONDS; |
| } else if (anyOf(unitName, "s", "sec", "second", "seconds")) { |
| unit = TimeUnit.SECONDS; |
| } else if (anyOf(unitName, "m", "min", "minute", "minutes")) { |
| unit = TimeUnit.MINUTES; |
| } else if (anyOf(unitName, "h", "hr", "hour", "hours")) { |
| unit = TimeUnit.HOURS; |
| } else if (anyOf(unitName, "d", "day", "days")) { |
| unit = TimeUnit.DAYS; |
| } else { |
| return null; |
| } |
| |
| try { |
| if (digits.indexOf('.') == -1) { |
| long val = Long.parseLong(digits); |
| return new Duration(val * TimeUnit.MILLISECONDS.convert(1, unit)); |
| } else { |
| double val = Double.parseDouble(digits); |
| return new Duration((long) (val * TimeUnit.MILLISECONDS.convert(1, unit))); |
| } |
| } catch (NumberFormatException nfe) { |
| return null; |
| } |
| } |
| |
| /** |
| * Get a {@link CacheBuilder} from a config. |
| * |
| * @param config JGit config object. |
| * @param name name of the cache subsection under the "cache" section. |
| * @return a new cache builder. |
| */ |
| public static CacheBuilder<Object, Object> getCacheBuilder(Config config, String name) { |
| CacheBuilder<Object, Object> b = CacheBuilder.newBuilder(); |
| try { |
| if (config.getString("cache", name, "maximumWeight") != null) { |
| b.maximumWeight(config.getLong("cache", name, "maximumWeight", 20 << 20)); |
| } |
| if (config.getString("cache", name, "maximumSize") != null) { |
| b.maximumSize(config.getLong("cache", name, "maximumSize", 16384)); |
| } |
| Duration expireAfterWrite = getDuration(config, "cache", name, "expireAfterWrite", null); |
| if (expireAfterWrite != null) { |
| b.expireAfterWrite(expireAfterWrite.getMillis(), TimeUnit.MILLISECONDS); |
| } |
| Duration expireAfterAccess = getDuration(config, "cache", name, "expireAfterAccess", null); |
| if (expireAfterAccess != null) { |
| b.expireAfterAccess(expireAfterAccess.getMillis(), TimeUnit.MILLISECONDS); |
| } |
| // Add other methods as needed. |
| } catch (IllegalArgumentException e) { |
| throw new IllegalArgumentException("Error getting CacheBuilder for " + name, e); |
| } catch (IllegalStateException e) { |
| throw new IllegalStateException("Error getting CacheBuilder for " + name, e); |
| } |
| return b; |
| } |
| |
| /** |
| * Get a {@link TimeZone} from a config. |
| * |
| * @param config JGit config object. |
| * @param section section to read, e.g. "gitiles". |
| * @param subsection subsection to read, e.g. "subsection". |
| * @param name variable to read, e.g. "fixedTimeZone". |
| * @return a time zone read from parsing the specified config string value, or |
| * {@link Optional#absent()} if not present. As in the behavior of |
| * {@link TimeZone#getTimeZone(String)}, unknown time zones are treated as |
| * GMT. |
| */ |
| public static Optional<TimeZone> getTimeZone( |
| Config config, String section, String subsection, String name) { |
| String id = config.getString(section, subsection, name); |
| return id != null ? Optional.of(TimeZone.getTimeZone(id)) : Optional.<TimeZone>absent(); |
| } |
| |
| private static Matcher matcher(String pattern, String valStr) { |
| return Pattern.compile(pattern).matcher(valStr); |
| } |
| |
| private static boolean anyOf(String a, String... cases) { |
| return Iterables.any(ImmutableList.copyOf(cases), Predicates.equalTo(a.toLowerCase())); |
| } |
| |
| private ConfigUtil() {} |
| } |