From 6cbeee38fa5502baa5d75036ad2c0418cf808d56 Mon Sep 17 00:00:00 2001 From: Erik Hatcher Date: Fri, 22 Feb 2002 01:53:36 +0000 Subject: [PATCH] Here goes: propertyfile refactoring to hopefully fix all outstanding issues with it. "now" and "never" were removed as operations (didn't make sense). "never" was removed as a value (it caused a null pointer exception anyway). Other code cleanup (axing "m_" prefixes). Added "unit" attribute to defaulting to DAY. This was essentially the previous default, but it was far too confusing. Test cases beefed up to consider several scenarios. There may be more changes needed to satisfy other use cases, and certainly some previous (undocumented) behavior has been changed (for the better!). Is there a use-case for "never" as a value? git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271503 13f79535-47bb-0310-9956-ffa450edef68 --- docs/manual/OptionalTasks/propertyfile.html | 28 +- .../taskdefs/optional/propertyfile.xml | 43 ++ .../ant/taskdefs/optional/PropertyFile.java | 462 +++++++++--------- .../taskdefs/optional/PropertyFileTest.java | 37 ++ 4 files changed, 330 insertions(+), 240 deletions(-) diff --git a/docs/manual/OptionalTasks/propertyfile.html b/docs/manual/OptionalTasks/propertyfile.html index 33285054d..c8c197d06 100644 --- a/docs/manual/OptionalTasks/propertyfile.html +++ b/docs/manual/OptionalTasks/propertyfile.html @@ -2,12 +2,11 @@ PropertyFile Task - -

Ant PropertyFile Task User Manual

+

PropertyFile

by

-

Version 1.1 - 2001/01/28


Table of Contents

* </propertyfile>
* </target>

* @@ -113,7 +111,9 @@ import java.text.DecimalFormat; *

+ *
  • default
  • + *
  • unit
  • + * * *If type is unspecified, it defaults to string * @@ -136,21 +136,17 @@ import java.text.DecimalFormat; * date/time and used even if a valid date was * found in the property file. * - *
  • offset:
    valid for "-" or "+", the offset (default - * set to 1) will be added or subtracted from "int" or - * "date" type value.
  • - * * *String property types can only use the "=" operation. - *Date property types can only use the "never" or "now" operations. *Int property types can only use the "=", "-" or "+" operations.

    * *The message property is used for the property file header, with "\\" being - *a newline delimiter charater. + *a newline delimiter character. * * @author Thomas Christen chr@active.ch * @author Jeremy Mawson jem@loftinspace.com.au -*/ + * @author Erik Hatcher ehatcher@apache.org + */ public class PropertyFile extends Task { @@ -168,10 +164,10 @@ public class PropertyFile extends Task */ // Use this to prepend a message to the properties file - private String m_comment; + private String comment; - private Properties m_properties; - private File m_propertyfile; + private Properties properties; + private File propertyfile; private Vector entries = new Vector(); @@ -205,24 +201,24 @@ public class PropertyFile extends Task for (Enumeration e = entries.elements(); e.hasMoreElements(); ) { Entry entry = (Entry)e.nextElement(); - entry.executeOn(m_properties); + entry.executeOn(properties); } } private void readFile() throws BuildException { // Create the PropertyFile - m_properties = new Properties(); + properties = new Properties(); try { - if (m_propertyfile.exists()) + if (propertyfile.exists()) { - log("Updating property file: "+m_propertyfile.getAbsolutePath()); + log("Updating property file: "+propertyfile.getAbsolutePath()); FileInputStream fis = null; try { - fis = new FileInputStream(m_propertyfile); + fis = new FileInputStream(propertyfile); BufferedInputStream bis = new BufferedInputStream(fis); - m_properties.load(bis); + properties.load(bis); } finally { if (fis != null) { fis.close(); @@ -232,10 +228,10 @@ public class PropertyFile extends Task else { log("Creating new property file: "+ - m_propertyfile.getAbsolutePath()); + propertyfile.getAbsolutePath()); FileOutputStream out = null; try { - out = new FileOutputStream(m_propertyfile.getAbsolutePath()); + out = new FileOutputStream(propertyfile.getAbsolutePath()); out.flush(); } finally { if (out != null) { @@ -252,7 +248,7 @@ public class PropertyFile extends Task private void checkParameters() throws BuildException { - if (!checkParam(m_propertyfile)) + if (!checkParam(propertyfile)) { throw new BuildException("file token must not be null.", location); } @@ -260,12 +256,12 @@ public class PropertyFile extends Task public void setFile(File file) { - m_propertyfile = file; + propertyfile = file; } public void setComment(String hdr) { - m_comment = hdr; + comment = hdr; } private void writeFile() throws BuildException @@ -273,7 +269,7 @@ public class PropertyFile extends Task BufferedOutputStream bos = null; try { - bos = new BufferedOutputStream(new FileOutputStream(m_propertyfile)); + bos = new BufferedOutputStream(new FileOutputStream(propertyfile)); // Properties.store is not available in JDK 1.1 Method m = @@ -282,10 +278,10 @@ public class PropertyFile extends Task OutputStream.class, String.class} ); - m.invoke(m_properties, new Object[] {bos, m_comment}); + m.invoke(properties, new Object[] {bos, comment}); } catch (NoSuchMethodException nsme) { - m_properties.save(bos, m_comment); + properties.save(bos, comment); } catch (InvocationTargetException ite) { Throwable t = ite.getTargetException(); throw new BuildException(t, location); @@ -325,87 +321,85 @@ public class PropertyFile extends Task */ public static class Entry { - - final static String NOW_VALUE_ = "now"; - final static String NULL_VALUE_ = "never"; - - private final static int DEFAULT_INT_VALUE = 1; - private final static GregorianCalendar - DEFAULT_DATE_VALUE = new GregorianCalendar(); - - private String m_key = null; - private int m_type = Type.STRING_TYPE; - private int m_operation = Operation.EQUALS_OPER; - private String m_value = ""; - private String m_default = null; - private String m_pattern = null; + private final static int DEFAULT_INT_VALUE = 0; + private final static String DEFAULT_DATE_VALUE = "now"; + private final static String DEFAULT_STRING_VALUE = ""; + + private String key = null; + private int type = Type.STRING_TYPE; + private int operation = Operation.EQUALS_OPER; + private String value = null; + private String defaultValue = null; + private String pattern = null; + private int field = Calendar.DATE; public void setKey(String value) { - this.m_key = value; + this.key = value; } public void setValue(String value) { - this.m_value = value; + this.value = value; } public void setOperation(Operation value) { - int newOperation = Operation.toOperation(value.getValue()); - if (newOperation == Operation.NOW_VALUE) { - this.m_operation = Operation.EQUALS_OPER; - this.setValue(this.NOW_VALUE_); - } - else if (newOperation == Operation.NULL_VALUE) { - this.m_operation = Operation.EQUALS_OPER; - this.setValue(this.NULL_VALUE_); - } - else { - this.m_operation = newOperation; - } + this.operation = Operation.toOperation(value.getValue()); } public void setType(Type value) { - this.m_type = Type.toType(value.getValue()); + this.type = Type.toType(value.getValue()); } public void setDefault(String value) { - this.m_default = value; + this.defaultValue = value; } public void setPattern(String value) { - this.m_pattern = value; + this.pattern = value; + } + + /** + * @since 1.15, Ant 1.5 + */ + public void setUnit(PropertyFile.Unit unit) { + field = unit.getCalendarField(); } protected void executeOn(Properties props) throws BuildException { checkParameters(); - // m_type may be null because it wasn't set + // type may be null because it wasn't set + String oldValue = (String)props.get(key); try { - if (m_type == Type.INTEGER_TYPE) + if (type == Type.INTEGER_TYPE) { - executeInteger((String)props.get(m_key)); + executeInteger(oldValue); } - else if (m_type == Type.DATE_TYPE) + else if (type == Type.DATE_TYPE) { - executeDate((String)props.get(m_key)); + executeDate(oldValue); } - else if (m_type == Type.STRING_TYPE) + else if (type == Type.STRING_TYPE) { - executeString((String)props.get(m_key)); + executeString(oldValue); } else { - throw new BuildException("Unknown operation type: "+m_type+""); + throw new BuildException("Unknown operation type: "+type+""); } } catch (NullPointerException npe) { // Default to string type // which means do nothing npe.printStackTrace(); } + + if (value == null) { + value = ""; + } + // Insert as a string by default - props.put(m_key, m_value); - + props.put(key, value); } /** @@ -417,93 +411,43 @@ public class PropertyFile extends Task */ private void executeDate(String oldValue) throws BuildException { - GregorianCalendar value = new GregorianCalendar(); - GregorianCalendar newValue = new GregorianCalendar(); + Calendar currentValue = Calendar.getInstance(); - if (m_pattern == null) { - m_pattern = "yyyy/MM/dd HH:mm"; - } - DateFormat fmt = new SimpleDateFormat(m_pattern); - - // special case - if (m_default != null && - NOW_VALUE_.equals(m_default.toLowerCase()) && - (m_operation == Operation.INCREMENT_OPER || - m_operation == Operation.DECREMENT_OPER) ) { - oldValue = null; + if (pattern == null) { + pattern = "yyyy/MM/dd HH:mm"; } + DateFormat fmt = new SimpleDateFormat(pattern); - if (oldValue != null) { + String currentStringValue = getCurrentValue(oldValue); + if (currentStringValue == null) { + currentStringValue = DEFAULT_DATE_VALUE; + } + + if ("now".equals(currentStringValue)) { + currentValue.setTime(new Date()); + } + else { try { - value.setTime(fmt.parse(oldValue)); + currentValue.setTime(fmt.parse(currentStringValue)); } catch (ParseException pe) { /* swollow */ } } - - if (m_value != null) { - if (NOW_VALUE_.equals(m_value.toLowerCase())) { - value.setTime(new Date()); - } - else if (NULL_VALUE_.equals(m_value.toLowerCase())) { - value = null; - } - else { - try { - value.setTime(fmt.parse(m_value)); - } - catch (Exception ex) { - // obviously not a date, try a simple int - try { - int offset = Integer.parseInt(m_value); - value.clear(); - value.set(Calendar.DAY_OF_YEAR, offset); - } - catch (Exception ex_) { - value.clear(); - value.set(Calendar.DAY_OF_YEAR, 1); - } + + if (operation != Operation.EQUALS_OPER) { + int offset = 0; + try { + offset = Integer.parseInt(value); + if (operation == Operation.DECREMENT_OPER) { + offset = -1 * offset; } - - } - } - - if (m_default != null && oldValue == null) { - if (NOW_VALUE_.equals(m_default.toLowerCase())) { - value.setTime(new Date()); - } - else if (NULL_VALUE_.equals(m_default.toLowerCase())) { - value = null; } - else { - try { - value.setTime(fmt.parse(m_default)); - } - catch (ParseException pe) { /* swollow */ } + catch (NumberFormatException e) { + throw new BuildException("Value not an integer on " + key); } + currentValue.add(field, offset); } - - if (m_operation == Operation.EQUALS_OPER) { - newValue = value; - } - else if (m_operation == Operation.INCREMENT_OPER) { - newValue.add(Calendar.SECOND, value.get(Calendar.SECOND)); - newValue.add(Calendar.MINUTE, value.get(Calendar.MINUTE)); - newValue.add(Calendar.HOUR_OF_DAY, value.get(Calendar.HOUR_OF_DAY)); - newValue.add(Calendar.DAY_OF_YEAR, value.get(Calendar.DAY_OF_YEAR)); - } - else if (m_operation == Operation.DECREMENT_OPER) { - newValue.add(Calendar.SECOND, -1 * value.get(Calendar.SECOND)); - newValue.add(Calendar.MINUTE, -1 * value.get(Calendar.MINUTE)); - newValue.add(Calendar.HOUR_OF_DAY, -1 * value.get(Calendar.HOUR_OF_DAY)); - newValue.add(Calendar.DAY_OF_YEAR, -1 * value.get(Calendar.DAY_OF_YEAR)); - } - if (newValue != null) { - m_value = fmt.format(newValue.getTime()); - } - else { - m_value = ""; - } + value = fmt.format(currentValue.getTime()); } @@ -516,66 +460,40 @@ public class PropertyFile extends Task */ private void executeInteger(String oldValue) throws BuildException { - int value = 0; // the value given in the 'value' attr - int newValue = 0; // the new value, after the operation - int oldIntValue = 0; // the old value from the prop file + int currentValue = DEFAULT_INT_VALUE; + int newValue = DEFAULT_INT_VALUE; - DecimalFormat fmt = (m_pattern != null) ? new DecimalFormat(m_pattern) - : new DecimalFormat(); - if (oldValue != null) { - try { - oldIntValue = fmt.parse(oldValue).intValue(); - } - catch (NumberFormatException nfe) { /* swollow */ } - catch (ParseException pe) { /* swollow */ } + DecimalFormat fmt = (pattern != null) ? new DecimalFormat(pattern) + : new DecimalFormat(); + try { + currentValue = fmt.parse(getCurrentValue(oldValue)).intValue(); } - if (m_value != null) { - try { - value = fmt.parse(m_value).intValue(); - } - catch (NumberFormatException nfe) { /* swollow */ } - catch (ParseException pe) { /* swollow */ } + catch (NumberFormatException nfe) { /* swollow */ } + catch (ParseException pe) { /* swollow */ } + + if (operation == Operation.EQUALS_OPER) { + newValue = currentValue; } - if (m_default != null && oldValue == null) { + else { + int operationValue = 1; try { - oldIntValue = fmt.parse(m_default).intValue(); + operationValue = fmt.parse(value).intValue(); } catch (NumberFormatException nfe) { /* swollow */ } catch (ParseException pe) { /* swollow */ } - } - - if (m_operation == Operation.EQUALS_OPER) { - newValue = oldIntValue; - } - else if (m_operation == Operation.INCREMENT_OPER) { - if (m_value == "") { - // No value attr was given, so just increment the - // old value from the prop file (0 by assignment above, - // if none). - newValue = ++oldIntValue; - } else { - // A value attr was given, so add the old value from - // the prop file (0, if none) to the specified value. - newValue = (oldIntValue + value) ; + + if (operation == Operation.INCREMENT_OPER) { + newValue = currentValue + operationValue; } - } - else if (m_operation == Operation.DECREMENT_OPER) { - if (m_value == "") { - // No value attr was given, so just decrement the - // old value from the prop file (0 by assignment above, - // if none). - newValue = --oldIntValue; - } else { - // A value attr was given, so subtract from the - // old value from the prop file (0, if none) the - // specified value. - newValue = (oldIntValue - value); + else if (operation == Operation.DECREMENT_OPER) { + newValue = currentValue - operationValue; } } - m_value = fmt.format(newValue); - } + value = fmt.format(newValue); + } + /** * Handle operations for type string. * @@ -585,55 +503,89 @@ public class PropertyFile extends Task */ private void executeString(String oldValue) throws BuildException { - String value = ""; - String newValue = ""; + String newValue = DEFAULT_STRING_VALUE; - // the order of events is, of course, very important here - // default initially to the old value - if (oldValue != null) { - value = oldValue; - } - // but if a value is specified, use it - if (m_value != null) { - value = m_value; - } - // even if value is specified, ignore it and set to the default - // value if it is specified and there is no previous value - if (m_default != null && oldValue == null) { - value = m_default; + String currentValue = getCurrentValue(oldValue); + + if (currentValue == null) { + currentValue = DEFAULT_STRING_VALUE; } - if (m_operation == Operation.EQUALS_OPER) { - newValue = value; + if (operation == Operation.EQUALS_OPER) { + newValue = currentValue; } - else if (m_operation == Operation.INCREMENT_OPER) { - newValue += value; + else if (operation == Operation.INCREMENT_OPER) { + newValue = currentValue + value; } - m_value = newValue; + value = newValue; } /** * Check if parameter combinations can be supported + * @todo make sure the 'unit' attribute is only specified on date + * fields */ private void checkParameters() throws BuildException { - if (m_type == Type.STRING_TYPE && - m_operation == Operation.DECREMENT_OPER) { - throw new BuildException("- is not suported for string properties (key:" + m_key + ")"); + if (type == Type.STRING_TYPE && + operation == Operation.DECREMENT_OPER) { + throw new BuildException("- is not suported for string properties (key:" + key + ")"); } - if (m_value == null && m_default == null) { - throw new BuildException("value and/or default must be specified (key:" + m_key + ")"); + if (value == null && defaultValue == null) { + throw new BuildException("value and/or default must be specified (key:" + key + ")"); } - if (m_key == null) { + if (key == null) { throw new BuildException("key is mandatory"); } - if (m_type == Type.STRING_TYPE && - m_pattern != null) { - throw new BuildException("pattern is not suported for string properties (key:" + m_key + ")"); + if (type == Type.STRING_TYPE && + pattern != null) { + throw new BuildException("pattern is not suported for string properties (key:" + key + ")"); } } + private String getCurrentValue(String oldValue) { + String ret = null; + if (operation == Operation.EQUALS_OPER) { + // If only value is specified, the property is set to it + // regardless of its previous value. + if (value != null && defaultValue == null) { + ret = value; + } + + // If only default is specified and the property previously + // existed in the property file, it is unchanged. + if (value == null && defaultValue != null && oldValue != null) { + ret = oldValue; + } + + // If only default is specified and the property did not + // exist in the property file, the property is set to default. + if (value == null && defaultValue != null && oldValue == null) { + ret = defaultValue; + } + + // If value and default are both specified and the property + // previously existed in the property file, the property + // is set to value. + if (value != null && defaultValue != null && oldValue != null) { + ret = value; + } + + // If value and default are both specified and the property + // did not exist in the property file, the property is set + // to default. + if (value != null && defaultValue != null && oldValue == null) { + ret = defaultValue; + } + } + else { + ret = (oldValue == null) ? defaultValue : oldValue; + } + + return ret; + } + /** - * Enumerated attribute with the values "+", "-", "=", "now" and "never". + * Enumerated attribute with the values "+", "-", "=" */ public static class Operation extends EnumeratedAttribute { @@ -642,12 +594,8 @@ public class PropertyFile extends Task public final static int DECREMENT_OPER = 1; public final static int EQUALS_OPER = 2; - // Special values - public final static int NOW_VALUE = 3; - public final static int NULL_VALUE = 4; - public String[] getValues() { - return new String[] {"+", "-", "=", NOW_VALUE_, NULL_VALUE_}; + return new String[] {"+", "-", "="}; } public static int toOperation(String oper) { @@ -657,12 +605,6 @@ public class PropertyFile extends Task else if ("-".equals(oper)) { return DECREMENT_OPER; } - else if (NOW_VALUE_.equals(oper)) { - return NOW_VALUE; - } - else if (NULL_VALUE_.equals(oper)) { - return NULL_VALUE; - } return EQUALS_OPER; } } @@ -692,4 +634,56 @@ public class PropertyFile extends Task } } } + + /** + * Borrowed from Tstamp + * + * @since 1.15, Ant 1.5 + */ + public static class Unit extends EnumeratedAttribute { + + private final static String MILLISECOND = "millisecond"; + private final static String SECOND = "second"; + private final static String MINUTE = "minute"; + private final static String HOUR = "hour"; + private final static String DAY = "day"; + private final static String WEEK = "week"; + private final static String MONTH = "month"; + private final static String YEAR = "year"; + + private final static String[] units = { + MILLISECOND, + SECOND, + MINUTE, + HOUR, + DAY, + WEEK, + MONTH, + YEAR + }; + + private Hashtable calendarFields = new Hashtable(); + + public Unit() { + calendarFields.put(MILLISECOND, + new Integer(Calendar.MILLISECOND)); + calendarFields.put(SECOND, new Integer(Calendar.SECOND)); + calendarFields.put(MINUTE, new Integer(Calendar.MINUTE)); + calendarFields.put(HOUR, new Integer(Calendar.HOUR_OF_DAY)); + calendarFields.put(DAY, new Integer(Calendar.DATE)); + calendarFields.put(WEEK, new Integer(Calendar.WEEK_OF_YEAR)); + calendarFields.put(MONTH, new Integer(Calendar.MONTH)); + calendarFields.put(YEAR, new Integer(Calendar.YEAR)); + } + + public int getCalendarField() { + String key = getValue().toLowerCase(); + Integer i = (Integer) calendarFields.get(key); + return i.intValue(); + } + + public String[] getValues() { + return units; + } + } } diff --git a/src/testcases/org/apache/tools/ant/taskdefs/optional/PropertyFileTest.java b/src/testcases/org/apache/tools/ant/taskdefs/optional/PropertyFileTest.java index 07ef8891f..4852a655c 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/optional/PropertyFileTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/optional/PropertyFileTest.java @@ -121,6 +121,42 @@ public class PropertyFileTest extends BuildFileTest { assertEquals(NEW_DATE, afterUpdate.getProperty(DATE_KEY)); } + public void testExerciseDefaultAndIncrement() throws Exception { + executeTarget("exercise"); + assertEquals("3",project.getProperty("int.with.default")); + assertEquals("1",project.getProperty("int.without.default")); + assertEquals("-->",project.getProperty("string.with.default")); + assertEquals(".",project.getProperty("string.without.default")); + assertEquals("2002/01/21 12:18", project.getProperty("ethans.birth")); + assertEquals("2003/01/21", project.getProperty("first.birthday")); + assertEquals("0124", project.getProperty("olderThanAWeek")); + assertEquals("37", project.getProperty("existing.prop")); + } + +/* + public void testDirect() throws Exception { + PropertyFile pf = new PropertyFile(); + pf.setProject(project); + pf.setFile(new File(testPropsFilePath)); + PropertyFile.Entry entry = pf.createEntry(); + + entry.setKey("date"); + entry.setValue("123"); + PropertyFile.Entry.Type type = new PropertyFile.Entry.Type(); + type.setValue("date"); + entry.setType(type); + + entry.setPattern("yyyy/MM/dd"); + + PropertyFile.Entry.Operation operation = new PropertyFile.Entry.Operation(); + operation.setValue("+"); + pf.execute(); + + Properties props = getTestProperties(); + assertEquals("yeehaw", props.getProperty("date")); + } +*/ + private Properties getTestProperties() throws Exception { Properties testProps = new Properties(); FileInputStream propsFile = new FileInputStream(testPropsFilePath); @@ -135,6 +171,7 @@ public class PropertyFileTest extends BuildFileTest { testProps.put(FNAME_KEY, FNAME); testProps.put(LNAME_KEY, LNAME); testProps.put(EMAIL_KEY, EMAIL); + testProps.put("existing.prop", "37"); FileOutputStream fos = new FileOutputStream(testPropsFilePath); testProps.save(fos, "defaults");