001 /*
002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org
003 * Copyright (C) 2011 NightLabs Consulting GmbH
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program. If not, see <http://www.gnu.org/licenses/>.
017 */
018 package org.cumulus4j.keymanager.cli;
019
020 import org.kohsuke.args4j.CmdLineException;
021 import org.kohsuke.args4j.CmdLineParser;
022 import org.kohsuke.args4j.Option;
023 import org.kohsuke.args4j.OptionDef;
024 import org.kohsuke.args4j.spi.OneArgumentOptionHandler;
025 import org.kohsuke.args4j.spi.Setter;
026
027 /**
028 * <p>
029 * Option handler implementation to interprete a time period (e.g. "5 minutes".
030 * </p>
031 * <p>
032 * The time period is specified in the command line by writing a number
033 * directly followed (no space!) by a unit. For example 5 minutes could be
034 * written as "5min" or "300s" (300 seconds are 5 minutes).
035 * </p>
036 * <p>
037 * This handler can be chosen for every <code>long</code> property using
038 * the {@link Option} annotation like this:
039 * </p>
040 * <pre>
041 * @Option(name="-myArg", handler=TimePeriodOptionHandler.class)
042 * private long myArg;
043 * </pre>
044 * <p>
045 * The <code>long</code> property will be set to the milliseconds value.
046 * For example, if the command line user passes "5min", the <code>long</code> value
047 * will be 300000 (5 min * 60 s * 1000 ms).
048 * </p>
049 *
050 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
051 */
052 public class TimePeriodOptionHandler extends OneArgumentOptionHandler<Long>
053 {
054 /**
055 * Units based on <a target="_blank" href="http://en.wikipedia.org/wiki/ISO_31-1">ISO 31-1</a> (where it exists).
056 *
057 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
058 */
059 public static enum Unit {
060 /**
061 * Millisecond.
062 */
063 ms("Millisecond", 1L),
064
065 /**
066 * Second.
067 */
068 s("Second", 1000L),
069
070 /**
071 * Minute.
072 */
073 min("Minute", 60L * s.msec),
074
075 /**
076 * Hour.
077 */
078 h("Hour", 60L * min.msec),
079
080 /**
081 * Day.
082 */
083 d("Day", 24L * h.msec),
084
085 /**
086 * Year. <a target="_blank" href="http://en.wikipedia.org/wiki/Year">Abbreviation from latin "annus".</a>
087 */
088 a("Year", 365L * d.msec),
089
090 /**
091 * Year (alternative for convenience).
092 */
093 y("Year", 365L * d.msec)
094 ;
095
096 private String displayName;
097 private long msec;
098
099 private Unit(String displayName, long msec)
100 {
101 this.displayName = displayName;
102 this.msec = msec;
103 }
104
105 public long toMSec(long value)
106 {
107 return value * msec;
108 }
109
110 public String getDisplayName() {
111 return displayName;
112 }
113
114 public static String getAllUnitsWithDisplayName()
115 {
116 return getAllUnitsWithDisplayName(", ");
117 }
118
119 public static String getAllUnitsWithDisplayName(String separator)
120 {
121 return getAllUnitsWithDisplayName("%s (%s)", separator);
122 }
123
124 public static String getAllUnitsWithDisplayName(String unitFormat, String separator)
125 {
126 StringBuilder sb = new StringBuilder();
127
128 for (Unit u : values()) {
129 if (sb.length() > 0)
130 sb.append(separator);
131
132 sb.append(String.format(unitFormat, u.name(), u.getDisplayName()));
133 }
134
135 return sb.toString();
136 }
137 }
138
139 public TimePeriodOptionHandler(CmdLineParser parser, OptionDef option, Setter<Long> setter)
140 {
141 super(parser, option, setter);
142 }
143
144 @Override
145 protected Long parse(String argument) throws NumberFormatException, CmdLineException
146 {
147 Unit unit = null;
148 for (Unit u : Unit.values()) {
149 if (argument.endsWith(u.name()) && (unit == null || unit.name().length() < u.name().length()))
150 unit = u;
151 }
152
153 if (unit == null)
154 throw new CmdLineException(owner, "Argument '" + argument + "' does not end with one of the following unit-suffixes: " + Unit.getAllUnitsWithDisplayName());
155
156 String numberVal = argument.substring(0, argument.length() - unit.name().length()).trim();
157 long valueMSec = Long.parseLong(numberVal);
158 return unit.toMSec(valueMSec);
159 }
160
161 }