From 82f7055c3e823a58e0d747cc782f8cf9eed913aa Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Tue, 24 Apr 2007 08:21:24 +0000
Subject: [PATCH] This change (no associated issue no.) addresses some counter-intuitive behavior discovered when specifying some duration based properties:

---
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/SizeUnitTest.java                   |   72 ++++++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/DurationUnitTest.java               |    3 
 opendj-sdk/opends/src/server/org/opends/server/admin/SizePropertyDefinition.java                                 |    6 
 opendj-sdk/opends/src/server/org/opends/server/admin/DurationPropertyDefinition.java                             |  147 +++++++++-----
 opendj-sdk/opends/resource/admin/property-types/duration.xsl                                                     |    8 
 opendj-sdk/opends/src/server/org/opends/server/admin/DurationUnit.java                                           |  210 ++++++++++++++------
 opendj-sdk/opends/src/server/org/opends/server/admin/SizeUnit.java                                               |   49 ++++
 opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ConfigurableEnvironment.java                         |    2 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/DurationPropertyDefinitionTest.java |   78 +++++--
 9 files changed, 412 insertions(+), 163 deletions(-)

diff --git a/opendj-sdk/opends/resource/admin/property-types/duration.xsl b/opendj-sdk/opends/resource/admin/property-types/duration.xsl
index acd3506..0282991 100644
--- a/opendj-sdk/opends/resource/admin/property-types/duration.xsl
+++ b/opendj-sdk/opends/resource/admin/property-types/duration.xsl
@@ -56,13 +56,13 @@
     </xsl:if>
     <xsl:if test="boolean(@upper-limit)">
       <xsl:value-of
-        select="concat('      builder.setUpperLimit(',
-                       @upper-limit, 'L);&#xa;')" />
+        select="concat('      builder.setUpperLimit(&quot;',
+                       @upper-limit, '&quot;);&#xa;')" />
     </xsl:if>
     <xsl:if test="boolean(@lower-limit)">
       <xsl:value-of
-        select="concat('      builder.setLowerLimit(',
-                       @lower-limit, 'L);&#xa;')" />
+        select="concat('      builder.setLowerLimit(&quot;',
+                       @lower-limit, '&quot;);&#xa;')" />
     </xsl:if>
   </xsl:template>
 </xsl:stylesheet>
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/DurationPropertyDefinition.java b/opendj-sdk/opends/src/server/org/opends/server/admin/DurationPropertyDefinition.java
index 45046ed..1d1915e 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/DurationPropertyDefinition.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/DurationPropertyDefinition.java
@@ -76,17 +76,16 @@
   // String used to represent unlimited durations.
   private static final String UNLIMITED = "unlimited";
 
-  // The base unit for this property definition (values including
-  // limits are specified in this unit).
+  // The base unit for this property definition.
   private final DurationUnit baseUnit;
 
   // The optional maximum unit for this property definition.
   private final DurationUnit maximumUnit;
 
-  // The lower limit of the property value.
+  // The lower limit of the property value in milli-seconds.
   private final long lowerLimit;
 
-  // The optional upper limit of the property value.
+  // The optional upper limit of the property value in milli-seconds.
   private final Long upperLimit;
 
   // Indicates whether this property allows the use of the "unlimited"
@@ -103,17 +102,17 @@
   public static class Builder extends
       AbstractBuilder<Long, DurationPropertyDefinition> {
 
-    // The base unit for this property definition (values including
-    // limits are specified in this unit).
+    // The base unit for this property definition.
     private DurationUnit baseUnit = DurationUnit.SECONDS;
 
     // The optional maximum unit for this property definition.
     private DurationUnit maximumUnit = null;
 
-    // The lower limit of the property value.
+    // The lower limit of the property value in milli-seconds.
     private long lowerLimit = 0L;
 
-    // The optional upper limit of the property value.
+    // The optional upper limit of the property value in
+    // milli-seconds.
     private Long upperLimit = null;
 
     // Indicates whether this property allows the use of the
@@ -124,8 +123,8 @@
 
 
     // Private constructor
-    private Builder(
-        AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
+    private Builder(AbstractManagedObjectDefinition<?, ?> d,
+        String propertyName) {
       super(d, propertyName);
     }
 
@@ -144,8 +143,7 @@
      *           known duration unit, or if the base unit is bigger
      *           than the maximum unit.
      */
-    public final void setBaseUnit(String unit)
-        throws IllegalArgumentException {
+    public final void setBaseUnit(String unit) throws IllegalArgumentException {
       ensureNotNull(unit);
 
       setBaseUnit(DurationUnit.getUnit(unit));
@@ -234,10 +232,10 @@
 
 
     /**
-     * Set the lower limit.
+     * Set the lower limit in milli-seconds.
      *
      * @param lowerLimit
-     *          The new lower limit (must be >= 0).
+     *          The new lower limit (must be >= 0) in milli-seconds.
      * @throws IllegalArgumentException
      *           If a negative lower limit was specified, or the lower
      *           limit is greater than the upper limit.
@@ -259,11 +257,30 @@
 
 
     /**
-     * Set the upper limit.
+     * Set the lower limit using a string representation of the limit.
+     * If the string does not specify a unit, the current base unit
+     * will be used.
+     *
+     * @param lowerLimit
+     *          The string representation of the new lower limit.
+     * @throws IllegalArgumentException
+     *           If the lower limit could not be parsed, or if a
+     *           negative lower limit was specified, or the lower
+     *           limit is greater than the upper limit.
+     */
+    public final void setLowerLimit(String lowerLimit)
+        throws IllegalArgumentException {
+      setLowerLimit(DurationUnit.parseValue(lowerLimit, baseUnit));
+    }
+
+
+
+    /**
+     * Set the upper limit in milli-seconds.
      *
      * @param upperLimit
-     *          The new upper limit or <code>null</code> if there is
-     *          no upper limit.
+     *          The new upper limit in milli-seconds, or
+     *          <code>null</code> if there is no upper limit.
      * @throws IllegalArgumentException
      *           If a negative upper limit was specified, or the lower
      *           limit is greater than the upper limit or unlimited
@@ -293,6 +310,29 @@
 
 
     /**
+     * Set the upper limit using a string representation of the limit.
+     * If the string does not specify a unit, the current base unit
+     * will be used.
+     *
+     * @param upperLimit
+     *          The string representation of the new upper limit, or
+     *          <code>null</code> if there is no upper limit.
+     * @throws IllegalArgumentException
+     *           If the upper limit could not be parsed, or if the
+     *           lower limit is greater than the upper limit.
+     */
+    public final void setUpperLimit(String upperLimit)
+        throws IllegalArgumentException {
+      if (upperLimit == null) {
+        setUpperLimit((Long) null);
+      } else {
+        setUpperLimit(DurationUnit.parseValue(upperLimit, baseUnit));
+      }
+    }
+
+
+
+    /**
      * Specify whether or not this property definition will allow
      * unlimited values (default is false).
      *
@@ -320,12 +360,12 @@
      */
     @Override
     protected DurationPropertyDefinition buildInstance(
-        AbstractManagedObjectDefinition<?, ?> d,
-        String propertyName, EnumSet<PropertyOption> options,
+        AbstractManagedObjectDefinition<?, ?> d, String propertyName,
+        EnumSet<PropertyOption> options,
         DefaultBehaviorProvider<Long> defaultBehavior) {
       return new DurationPropertyDefinition(d, propertyName, options,
-          defaultBehavior, baseUnit, maximumUnit, lowerLimit,
-          upperLimit, allowUnlimited);
+          defaultBehavior, baseUnit, maximumUnit, lowerLimit, upperLimit,
+          allowUnlimited);
     }
   }
 
@@ -341,20 +381,19 @@
    *          The property name.
    * @return Returns the new integer property definition builder.
    */
-  public static Builder createBuilder(
-      AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
+  public static Builder createBuilder(AbstractManagedObjectDefinition<?, ?> d,
+      String propertyName) {
     return new Builder(d, propertyName);
   }
 
 
 
   // Private constructor.
-  private DurationPropertyDefinition(
-      AbstractManagedObjectDefinition<?, ?> d, String propertyName,
-      EnumSet<PropertyOption> options,
-      DefaultBehaviorProvider<Long> defaultBehavior,
-      DurationUnit baseUnit, DurationUnit maximumUnit,
-      Long lowerLimit, Long upperLimit, boolean allowUnlimited) {
+  private DurationPropertyDefinition(AbstractManagedObjectDefinition<?, ?> d,
+      String propertyName, EnumSet<PropertyOption> options,
+      DefaultBehaviorProvider<Long> defaultBehavior, DurationUnit baseUnit,
+      DurationUnit maximumUnit, Long lowerLimit, Long upperLimit,
+      boolean allowUnlimited) {
     super(d, Long.class, propertyName, options, defaultBehavior);
     this.baseUnit = baseUnit;
     this.maximumUnit = maximumUnit;
@@ -391,9 +430,9 @@
 
 
   /**
-   * Get the lower limit.
+   * Get the lower limit in milli-seconds.
    *
-   * @return Returns the lower limit.
+   * @return Returns the lower limit in milli-seconds.
    */
   public long getLowerLimit() {
     return lowerLimit;
@@ -402,10 +441,10 @@
 
 
   /**
-   * Get the upper limit.
+   * Get the upper limit in milli-seconds.
    *
-   * @return Returns the upper limit or <code>null</code> if there
-   *         is no upper limit.
+   * @return Returns the upper limit in milli-seconds, or
+   *         <code>null</code> if there is no upper limit.
    */
   public Long getUpperLimit() {
     return upperLimit;
@@ -429,19 +468,19 @@
    * {@inheritDoc}
    */
   @Override
-  public void validateValue(Long value)
-      throws IllegalPropertyValueException {
+  public void validateValue(Long value) throws IllegalPropertyValueException {
     ensureNotNull(value);
 
-    if (!allowUnlimited && value < lowerLimit) {
+    long nvalue = baseUnit.toMilliSeconds(value);
+    if (!allowUnlimited && nvalue < lowerLimit) {
       throw new IllegalPropertyValueException(this, value);
 
       // unlimited allowed
-    } else if (value >= 0 && value < lowerLimit) {
+    } else if (nvalue >= 0 && nvalue < lowerLimit) {
       throw new IllegalPropertyValueException(this, value);
     }
 
-    if ((upperLimit != null) && (value > upperLimit)) {
+    if ((upperLimit != null) && (nvalue > upperLimit)) {
       throw new IllegalPropertyValueException(this, value);
     }
   }
@@ -452,8 +491,7 @@
    * {@inheritDoc}
    */
   @Override
-  public String encodeValue(Long value)
-      throws IllegalPropertyValueException {
+  public String encodeValue(Long value) throws IllegalPropertyValueException {
     ensureNotNull(value);
 
     // Make sure that we correctly encode negative values as
@@ -489,8 +527,7 @@
     }
 
     // Value must be a floating point number followed by a unit.
-    Pattern p = Pattern
-        .compile("^\\s*(\\d+(\\.\\d*)?)\\s*(\\w+)\\s*$");
+    Pattern p = Pattern.compile("^\\s*(\\d+(\\.\\d+)?)\\s*(\\w+)\\s*$");
     Matcher m = p.matcher(value);
 
     if (!m.matches()) {
@@ -506,26 +543,32 @@
     }
 
     // Group 3 is the unit.
-    DurationUnit u;
-    try {
-      u = DurationUnit.getUnit(m.group(3));
-    } catch (IllegalArgumentException e) {
-      throw new IllegalPropertyValueStringException(this, value);
+    String unitString = m.group(3);
+    DurationUnit unit;
+    if (unitString == null) {
+      unit = baseUnit;
+    } else {
+      try {
+        unit = DurationUnit.getUnit(unitString);
+      } catch (IllegalArgumentException e) {
+        throw new IllegalPropertyValueStringException(this, value);
+      }
     }
 
     // Check the unit is in range.
-    if (u.getDuration() < baseUnit.getDuration()) {
+    if (unit.getDuration() < baseUnit.getDuration()) {
       throw new IllegalPropertyValueStringException(this, value);
     }
 
     if (maximumUnit != null) {
-      if (u.getDuration() > maximumUnit.getDuration()) {
+      if (unit.getDuration() > maximumUnit.getDuration()) {
         throw new IllegalPropertyValueStringException(this, value);
       }
     }
 
     // Convert the value a long in the property's required unit.
-    Long i = (long) u.getDuration(d, baseUnit);
+    long ms = unit.toMilliSeconds(d);
+    Long i = (long) baseUnit.fromMilliSeconds(ms);
     try {
       validateValue(i);
     } catch (IllegalPropertyValueException e) {
@@ -563,10 +606,12 @@
 
     builder.append(" lowerLimit=");
     builder.append(lowerLimit);
+    builder.append("ms");
 
     if (upperLimit != null) {
       builder.append(" upperLimit=");
       builder.append(upperLimit);
+      builder.append("ms");
     }
 
     builder.append(" allowUnlimited=");
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/DurationUnit.java b/opendj-sdk/opends/src/server/org/opends/server/admin/DurationUnit.java
index 2fa0c5a..7b8c0ae 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/DurationUnit.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/DurationUnit.java
@@ -30,6 +30,8 @@
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 
 
@@ -79,6 +81,99 @@
     }
   }
 
+
+
+  /**
+   * Get the unit corresponding to the provided unit name.
+   *
+   * @param s
+   *          The name of the unit. Can be the abbreviated or long
+   *          name and can contain white space and mixed case
+   *          characters.
+   * @return Returns the unit corresponding to the provided unit name.
+   * @throws IllegalArgumentException
+   *           If the provided name did not correspond to a known
+   *           duration unit.
+   */
+  public static DurationUnit getUnit(String s) throws IllegalArgumentException {
+    DurationUnit unit = nameToUnit.get(s.trim().toLowerCase());
+    if (unit == null) {
+      throw new IllegalArgumentException("Illegal duration unit \"" + s + "\"");
+    }
+    return unit;
+  }
+
+
+
+  /**
+   * Parse the provided duration string and return its equivalent
+   * duration in milli-seconds. The duration string must specify the
+   * unit e.g. "10s".
+   *
+   * @param s
+   *          The duration string to be parsed.
+   * @return Returns the parsed duration in milli-seconds.
+   * @throws NumberFormatException
+   *           If the provided duration string could not be parsed.
+   */
+  public static long parseValue(String s) throws NumberFormatException {
+    return parseValue(s, null);
+  }
+
+
+
+  /**
+   * Parse the provided duration string and return its equivalent
+   * duration in milli-seconds.
+   *
+   * @param s
+   *          The duration string to be parsed.
+   * @param defaultUnit
+   *          The default unit to use if there is no unit specified in
+   *          the duration string, or <code>null</code> if the
+   *          string must always contain a unit.
+   * @return Returns the parsed duration in milli-seconds.
+   * @throws NumberFormatException
+   *           If the provided duration string could not be parsed.
+   */
+  public static long parseValue(String s, DurationUnit defaultUnit)
+      throws NumberFormatException {
+    // Value must be a floating point number followed by a unit.
+    Pattern p = Pattern.compile("^\\s*(\\d+(\\.\\d+)?)\\s*(\\w+)?\\s*$");
+    Matcher m = p.matcher(s);
+
+    if (!m.matches()) {
+      throw new NumberFormatException("Invalid duration value \"" + s + "\"");
+    }
+
+    // Group 1 is the float.
+    double d;
+    try {
+      d = Double.valueOf(m.group(1));
+    } catch (NumberFormatException e) {
+      throw new NumberFormatException("Invalid duration value \"" + s + "\"");
+    }
+
+    // Group 3 is the unit.
+    String unitString = m.group(3);
+    DurationUnit unit;
+    if (unitString == null) {
+      if (defaultUnit == null) {
+        throw new NumberFormatException("Invalid duration value \"" + s + "\"");
+      } else {
+        unit = defaultUnit;
+      }
+    } else {
+      try {
+        unit = getUnit(unitString);
+      } catch (IllegalArgumentException e) {
+        throw new NumberFormatException("Invalid duration value \"" + s + "\"");
+      }
+    }
+
+    return unit.toMilliSeconds(d);
+  }
+
   // The size of the unit in milli-seconds.
   private final long sz;
 
@@ -100,32 +195,54 @@
 
 
   /**
-   * Get the unit corresponding to the provided unit name.
+   * Converts the specified duration in milli-seconds to this unit.
    *
-   * @param s
-   *          The name of the unit. Can be the abbreviated or long name and can
-   *          contain white space and mixed case characters.
-   * @return Returns the unit corresponding to the provided unit name.
-   * @throws IllegalArgumentException
-   *           If the provided name did not correspond to a known duration unit.
+   * @param duration
+   *          The duration in milli-seconds.
+   * @return Returns milli-seconds in this unit.
    */
-  public static DurationUnit getUnit(String s) throws IllegalArgumentException {
-    DurationUnit unit = nameToUnit.get(s.trim().toLowerCase());
-    if (unit == null) {
-      throw new IllegalArgumentException("Illegal duration unit \"" + s + "\"");
-    }
-    return unit;
+  public double fromMilliSeconds(long duration) {
+    return ((double) duration / sz);
   }
 
 
 
   /**
-   * Get the abbreviated name of this unit.
+   * Get the best-fit unit for the specified duration in this unit.
+   * For example, if this unit is minutes and the duration 120 is
+   * provided, then the best fit unit is hours: 2h. Similarly, if the
+   * duration is 0.5, then the best fit unit will by seconds: 30s.
    *
-   * @return Returns the abbreviated name of this unit.
+   * @param duration
+   *          The duration.
+   * @return Returns the best-fit unit for the specified duration in
+   *         this unit.
    */
-  public String getShortName() {
-    return shortName;
+  public DurationUnit getBestFitUnit(double duration) {
+    long ms = toMilliSeconds(duration);
+    if (ms == 0) {
+      return this;
+    } else if (ms > 0) {
+      for (DurationUnit unit : new DurationUnit[] { WEEKS, DAYS, HOURS,
+          MINUTES, SECONDS }) {
+        if ((ms % unit.sz) == 0) {
+          return unit;
+        }
+      }
+    }
+    return MILLI_SECONDS;
+  }
+
+
+
+  /**
+   * Get the number of milli-seconds that this unit represents.
+   *
+   * @return Returns the number of milli-seconds that this unit
+   *         represents.
+   */
+  public long getDuration() {
+    return sz;
   }
 
 
@@ -142,12 +259,12 @@
 
 
   /**
-   * Get the number of milli-seconds that this unit represents.
+   * Get the abbreviated name of this unit.
    *
-   * @return Returns the number of milli-seconds that this unit represents.
+   * @return Returns the abbreviated name of this unit.
    */
-  public long getDuration() {
-    return sz;
+  public String getShortName() {
+    return shortName;
   }
 
 
@@ -156,60 +273,21 @@
    * Converts the specified duration in this unit to milli-seconds.
    *
    * @param duration
-   *          The duration.
-   * @return Returns the number of milli-seconds that the duration represents.
+   *          The duration as a quantity of this unit.
+   * @return Returns the number of milli-seconds that the duration
+   *         represents.
    */
-  public long getDuration(double duration) {
+  public long toMilliSeconds(double duration) {
     return (long) (sz * duration);
   }
 
 
 
   /**
-   * Converts a duration in this unit to the specified unit.
-   *
-   * @param duration
-   *          The duration.
-   * @param unit
-   *          The required unit.
-   * @return Returns a value representing the duration in the specified unit.
-   */
-  public double getDuration(double duration, DurationUnit unit) {
-    return (sz * duration) / unit.sz;
-  }
-
-
-
-  /**
-   * Get the best-fit unit for the specified duration in this unit. For example,
-   * if this unit is minutes and the duration 120 is provided, then the best fit
-   * unit is hours: 2h. Similarly, if the duration is 0.5, then the best fit
-   * unit will by seconds: 30s.
-   *
-   * @param duration
-   *          The duration.
-   * @return Returns the best-fit unit for the specified duration in this unit.
-   */
-  public DurationUnit getBestFitUnit(double duration) {
-    for (DurationUnit unit :
-            new DurationUnit[]{WEEKS, DAYS, HOURS, MINUTES, SECONDS}) {
-      double v = getDuration(duration, unit);
-      if (Double.isInfinite(v) || Double.isNaN(v) || v == 0) {
-        return this;
-      }
-      if (v >= 1 && Math.floor(v) == Math.ceil(v)) {
-        return unit;
-      }
-    }
-    return MILLI_SECONDS;
-  }
-
-
-
-  /**
    * {@inheritDoc}
    * <p>
-   * This implementation returns the abbreviated name of this duration unit.
+   * This implementation returns the abbreviated name of this duration
+   * unit.
    */
   @Override
   public String toString() {
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/SizePropertyDefinition.java b/opendj-sdk/opends/src/server/org/opends/server/admin/SizePropertyDefinition.java
index cc58f1d..e9d89b7 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/SizePropertyDefinition.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/SizePropertyDefinition.java
@@ -130,7 +130,7 @@
      */
     public final void setLowerLimit(String lowerLimit)
         throws IllegalArgumentException {
-      setLowerLimit(SizeUnit.parseValue(lowerLimit));
+      setLowerLimit(SizeUnit.parseValue(lowerLimit, SizeUnit.BYTES));
     }
 
 
@@ -175,7 +175,7 @@
       if (upperLimit == null) {
         setUpperLimit((Long) null);
       } else {
-        setUpperLimit(SizeUnit.parseValue(upperLimit));
+        setUpperLimit(SizeUnit.parseValue(upperLimit, SizeUnit.BYTES));
       }
     }
 
@@ -344,7 +344,7 @@
     // Decode the value.
     Long i;
     try {
-      i = SizeUnit.parseValue(value);
+      i = SizeUnit.parseValue(value, SizeUnit.BYTES);
     } catch (NumberFormatException e) {
       throw new IllegalPropertyValueStringException(this, value);
     }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/SizeUnit.java b/opendj-sdk/opends/src/server/org/opends/server/admin/SizeUnit.java
index e4d4913..df735b2 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/SizeUnit.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/SizeUnit.java
@@ -121,17 +121,39 @@
 
 
   /**
-   * Parse the provided size string and return its equivalent size in bytes.
+   * Parse the provided size string and return its equivalent size in
+   * bytes. The size string must specify the unit e.g. "10kb".
    *
    * @param s
    *          The size string to be parsed.
-   * @return Returns the parsed size in bytes.
+   * @return Returns the parsed duration in bytes.
    * @throws NumberFormatException
    *           If the provided size string could not be parsed.
    */
   public static long parseValue(String s) throws NumberFormatException {
+    return parseValue(s, null);
+  }
+
+
+
+  /**
+   * Parse the provided size string and return its equivalent size in
+   * bytes.
+   *
+   * @param s
+   *          The size string to be parsed.
+   * @param defaultUnit
+   *          The default unit to use if there is no unit specified in
+   *          the size string, or <code>null</code> if the string
+   *          must always contain a unit.
+   * @return Returns the parsed size in bytes.
+   * @throws NumberFormatException
+   *           If the provided size string could not be parsed.
+   */
+  public static long parseValue(String s, SizeUnit defaultUnit)
+      throws NumberFormatException {
     // Value must be a floating point number followed by a unit.
-    Pattern p = Pattern.compile("^\\s*(\\d+(\\.\\d+)?)\\s*(\\w+)\\s*$");
+    Pattern p = Pattern.compile("^\\s*(\\d+(\\.\\d+)?)\\s*(\\w+)?\\s*$");
     Matcher m = p.matcher(s);
 
     if (!m.matches()) {
@@ -147,12 +169,23 @@
     }
 
     // Group 3 is the unit.
-    try {
-      SizeUnit u = getUnit(m.group(3));
-      return u.toBytes(d);
-    } catch (IllegalArgumentException e) {
-      throw new NumberFormatException("Invalid size value \"" + s + "\"");
+    String unitString = m.group(3);
+    SizeUnit unit;
+    if (unitString == null) {
+      if (defaultUnit == null) {
+        throw new NumberFormatException("Invalid size value \"" + s + "\"");
+      } else {
+        unit = defaultUnit;
+      }
+    } else {
+      try {
+        unit = getUnit(unitString);
+      } catch (IllegalArgumentException e) {
+        throw new NumberFormatException("Invalid size value \"" + s + "\"");
+      }
     }
+
+    return unit.toBytes(d);
   }
 
   // The size of the unit in bytes.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ConfigurableEnvironment.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ConfigurableEnvironment.java
index 4e49be3..aa26c19 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ConfigurableEnvironment.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ConfigurableEnvironment.java
@@ -276,7 +276,7 @@
         // JE durations are in microseconds so we must convert.
         DurationPropertyDefinition durationPropDefn =
              (DurationPropertyDefinition)propDefn;
-        value = 1000*durationPropDefn.getBaseUnit().getDuration(value);
+        value = 1000*durationPropDefn.getBaseUnit().toMilliSeconds(value);
 
         return String.valueOf(value);
       }
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/DurationPropertyDefinitionTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/DurationPropertyDefinitionTest.java
index e7e802e..ba8b869 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/DurationPropertyDefinitionTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/DurationPropertyDefinitionTest.java
@@ -56,7 +56,7 @@
     DurationPropertyDefinition.Builder builder = createTestBuilder();
     builder.setLowerLimit((long) 1);
     DurationPropertyDefinition spd = buildTestDefinition(builder);
-    assert spd.getLowerLimit() == 1;
+    assertEquals(spd.getLowerLimit(), 1);
   }
 
   /**
@@ -64,7 +64,7 @@
    * @return data
    */
   @DataProvider(name = "longLimitData")
-  public Object[][] createlongLimitData() {
+  public Object[][] createLongLimitData() {
     return new Object[][]{
             {1L, 1L},
             // { null, 0 }
@@ -92,11 +92,47 @@
    * @param expectedValue to compare
    */
   @Test(dataProvider = "longLimitData")
-  public void testLowerLimit2(long limit, Long expectedValue) {
+  public void testLowerLimit2(long limit, long expectedValue) {
     DurationPropertyDefinition.Builder builder = createTestBuilder();
     builder.setLowerLimit(limit);
     DurationPropertyDefinition spd = buildTestDefinition(builder);
-    assert spd.getLowerLimit() == expectedValue;
+    assertEquals(spd.getLowerLimit(), expectedValue);
+  }
+  
+  /**
+   * Creates data for testing string-based limit values
+   * 
+   * @return data
+   */
+  @DataProvider(name = "stringLimitData")
+  public Object[][] createStringLimitData() {
+    return new Object[][] {
+        { "ms", "123", 123 },
+        { "ms", "123s", 123000 },
+        { "s", "123", 123000 },
+        { "s", "123s", 123000 },
+        { "m", "10", 600000 },
+        { "m", "10s", 10000 }
+    };
+  }
+  
+  /**
+   * Tests setting/getting of lower limit as String.
+   * 
+   * @param unit
+   *          The unit.
+   * @param value
+   *          The limit value.
+   * @param expected
+   *          The expected limit in ms.
+   */
+  @Test(dataProvider = "stringLimitData")
+  public void testLowerLimit3(String unit, String value, long expected) {
+    DurationPropertyDefinition.Builder builder = createTestBuilder();
+    builder.setBaseUnit(DurationUnit.getUnit(unit));
+    builder.setLowerLimit(value);
+    DurationPropertyDefinition spd = buildTestDefinition(builder);
+    assertEquals(spd.getLowerLimit(), expected);
   }
 
   /**
@@ -107,7 +143,7 @@
     DurationPropertyDefinition.Builder builder = createTestBuilder();
     builder.setLowerLimit((long) 1);
     DurationPropertyDefinition spd = buildTestDefinition(builder);
-    assert spd.getLowerLimit() == 1;
+    assertEquals(spd.getLowerLimit(), 1);
   }
 
   /**
@@ -120,7 +156,7 @@
     DurationPropertyDefinition.Builder builder = createTestBuilder();
     builder.setUpperLimit(limit);
     DurationPropertyDefinition spd = buildTestDefinition(builder);
-    assert spd.getUpperLimit().equals(expectedValue);
+    assertEquals((long) spd.getUpperLimit(), expectedValue);
   }
 
   /**
@@ -179,13 +215,13 @@
    * @return data
    */
   @DataProvider(name = "validateValueData")
-  public Object[][] createvalidateValueData() {
+  public Object[][] createValidateValueData() {
     return new Object[][]{
-            {5L, 10L, false, 7L},
-            {5L, null, true, -1L},
-            {5L, 10L, false, 5L},
-            {5L, 10L, false, 10L},
-            {5L, null, false, 10000L}
+            {5000L, 10000L, false, 7L},
+            {5000L, null, true, -1L},
+            {5000L, 10000L, false, 5L},
+            {5000L, 10000L, false, 10L},
+            {5000L, null, false, 10000L}
     };
   }
 
@@ -213,10 +249,10 @@
   @DataProvider(name = "illegalValidateValueData")
   public Object[][] createIllegalValidateValueData() {
     return new Object[][]{
-            {5L, 10L, false, null},
-            {5L, 10L, false, 1L},
-            {5L, 10L, false, 11L},
-            {5L, 10L, false, -1L}
+            {5000L, 10000L, false, null},
+            {5000L, 10000L, false, 1L},
+            {5000L, 10000L, false, 11L},
+            {5000L, 10000L, false, -1L}
     };
   }
 
@@ -364,17 +400,13 @@
             // syntax tests
             {"unlimited", -1L},
             {"0h", 0L},
-            {"0.h", 0L},
             {"0.0h", 0L},
             {"0.00h", 0L},
             {"0 h", 0L},
-            {"0. h", 0L},
             {"0.00 h", 0L},
             {"1h", 1L},
-            {"1.h", 1L},
             {"1.1h", 1L},
             {"1 h", 1L},
-            {"1. h", 1L},
             {"1.1 h", 1L},
 
             // conversion tests
@@ -399,7 +431,7 @@
 //    if (spd.decodeValue(value) != expectedValue) {
 //      System.out.println(spd.decodeValue(value) + "!=" + expectedValue);
 //    }
-    assert(spd.decodeValue(value) == expectedValue);
+    assertEquals(spd.decodeValue(value), expectedValue);
   }
 
   /**
@@ -411,6 +443,10 @@
     return new Object[][]{
             {"a s"},
             {"1 x"},
+            {"0.h"},
+            {"0. h"},
+            {"1.h"},
+            {"1. h"},
             {"30 m"}, // unit too small violation
             {"60 m"}, // unit too small violation
             {"1 w"},  // unit too big violation
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/DurationUnitTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/DurationUnitTest.java
index 367cfab..0f8dece 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/DurationUnitTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/DurationUnitTest.java
@@ -82,12 +82,13 @@
     @DataProvider(name = "testGetBestFitUnit")
     public Object[][] createGetBestFitData() {
       return new Object[][]{
+              { SECONDS, 0, SECONDS },
               { MINUTES, 0, MINUTES },
+              { HOURS, 0, HOURS },
               { MINUTES, .5D, SECONDS },
               { MINUTES, 119D, MINUTES },
               { MINUTES, 120D, HOURS },
               { MINUTES, 121D, MINUTES },
-              { MINUTES, Double.MAX_VALUE, MINUTES },
               { MINUTES, Double.MIN_VALUE, MINUTES }
       };
     }
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/SizeUnitTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/SizeUnitTest.java
index fd66e6e..371f0cd 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/SizeUnitTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/SizeUnitTest.java
@@ -72,7 +72,7 @@
    * @return The array of illegal test DN strings.
    */
   @DataProvider(name = "parseValue1Data")
-  public Object[][] createParseValueData() {
+  public Object[][] createParseValue1Data() {
     return new Object[][]{
             {"1.0 b", 1L},
             {"1.0 kb", 1000L},
@@ -95,17 +95,17 @@
    * @param expectedValue for comparison
    */
   @Test(dataProvider = "parseValue1Data")
-  public void testParseValue1(String value, Long expectedValue) {
-    assert SizeUnit.parseValue(value) == expectedValue;
+  public void testParseValue1(String value, long expectedValue) {
+    assertEquals(SizeUnit.parseValue(value), expectedValue);
   }
 
   /**
    * Creates illegal data for testing String to SizeUnit conversions
    *
-   * @return The array of illegal test DN strings.
+   * @return The array of illegal test strings.
    */
   @DataProvider(name = "parseValue2Data")
-  public Object[][] createIllegalParseValueData() {
+  public Object[][] createParseValue2Data() {
     return new Object[][]{
             {"a.0 b"},
             {"1.a kb"},
@@ -130,6 +130,62 @@
   }
 
   /**
+   * Creates data for testing String to SizeUnit conversions
+   *
+   * @return The array of test strings.
+   */
+  @DataProvider(name = "parseValue3Data")
+  public Object[][] createParseValue3Data() {
+    return new Object[][]{
+            {"1.0 b", 1L},
+            {"1.0 kb", 1000L},
+            {"1.0 kib", 1024L},
+            {"1.0", 1000L},
+            {"1000", 1000000L},
+            {"1MB", 1000000L}
+    };
+  }
+
+  /**
+   * Tests parsing of SizeUnits specified as String values
+   * @param value to parse
+   * @param expectedValue for comparison
+   */
+  @Test(dataProvider = "parseValue3Data")
+  public void testParseValue3(String value, long expectedValue) {
+    assertEquals(SizeUnit.parseValue(value, SizeUnit.KILO_BYTES), expectedValue);
+  }
+
+  /**
+   * Creates illegal data for testing String to SizeUnit conversions
+   *
+   * @return The array of illegal test DN strings.
+   */
+  @DataProvider(name = "parseValue4Data")
+  public Object[][] createParseValue4Data() {
+    return new Object[][]{
+            {"a.0 b"},
+            {"1.a kb"},
+            {"1.0 xx"},
+            { "" },
+            { "hello" },
+            { "-1" },
+            { "-1b" },
+            { "1x" },
+            { "1.1y" }
+    };
+  }
+
+  /**
+   * Tests that illegal String specified SizeUnits throw exceptions
+   * @param value to parse
+   */
+  @Test(dataProvider = "parseValue4Data", expectedExceptions = NumberFormatException.class)
+  public void testParseValue4(String value) {
+    SizeUnit.parseValue(value, SizeUnit.KILO_BYTES);
+  }
+  
+  /**
    * Creates data for testing fromBytes
    *
    * @return data
@@ -150,7 +206,7 @@
    */
   @Test(dataProvider = "fromBytesTestData")
   public void testFromBytes(SizeUnit unit, long value, double expected) {
-    assert unit.fromBytes(value) == expected;
+    assertEquals(unit.fromBytes(value), expected);
   }
 
   /**
@@ -265,7 +321,7 @@
    */
   @Test(dataProvider = "sizeData")
   public void testGetSize(SizeUnit unit, long expectedSize) {
-    assert unit.getSize() == expectedSize;
+    assertEquals(unit.getSize(), expectedSize);
   }
 
   /**
@@ -287,7 +343,7 @@
    */
   @Test(dataProvider = "toBytesData")
   public void testToBytes(SizeUnit unit, double amt, long expected) {
-    assert unit.toBytes(amt) == expected;
+    assertEquals(unit.toBytes(amt), expected);
   }
 
   /**

--
Gitblit v1.10.0