diff --git a/build.xml b/build.xml
index add72bbbd..7d64dd3a7 100644
--- a/build.xml
+++ b/build.xml
@@ -1105,6 +1105,7 @@ under the License.
failureproperty="ooxml.test.failed">
+
@@ -1126,6 +1127,7 @@ under the License.
+
@@ -1715,6 +1717,7 @@ under the License.
+
@@ -1733,23 +1736,22 @@ under the License.
-
-
-
-
-
-
-
-
-
-
-
+ classpathref="javadoc.classpath"
+ suppressAnnotation="org.apache.poi.util.SuppressForbidden"
+ >
+
+
+
+
+
diff --git a/src/java/org/apache/poi/hssf/eventusermodel/FormatTrackingHSSFListener.java b/src/java/org/apache/poi/hssf/eventusermodel/FormatTrackingHSSFListener.java
index 1ca3db366..074c294c5 100644
--- a/src/java/org/apache/poi/hssf/eventusermodel/FormatTrackingHSSFListener.java
+++ b/src/java/org/apache/poi/hssf/eventusermodel/FormatTrackingHSSFListener.java
@@ -31,6 +31,7 @@ import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
+import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
@@ -52,7 +53,7 @@ public class FormatTrackingHSSFListener implements HSSFListener {
* the {@link Locale#getDefault() default locale} for the formats.
*/
public FormatTrackingHSSFListener(HSSFListener childListener) {
- this(childListener, Locale.getDefault());
+ this(childListener, LocaleUtil.getUserLocale());
}
/**
diff --git a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java
index a2670978e..7994f2820 100644
--- a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java
+++ b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java
@@ -22,7 +22,6 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
@@ -96,6 +95,7 @@ import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.Internal;
+import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
@@ -1774,7 +1774,7 @@ public final class InternalWorkbook {
retval.setDefaultCountry(( short ) 1);
// from Russia with love ;)
- if ( Locale.getDefault().toString().equals( "ru_RU" ) ) {
+ if ( LocaleUtil.getUserLocale().toString().equals( "ru_RU" ) ) {
retval.setCurrentCountry(( short ) 7);
}
else {
diff --git a/src/java/org/apache/poi/hssf/usermodel/DVConstraint.java b/src/java/org/apache/poi/hssf/usermodel/DVConstraint.java
index 4548486a4..41f90fbfc 100644
--- a/src/java/org/apache/poi/hssf/usermodel/DVConstraint.java
+++ b/src/java/org/apache/poi/hssf/usermodel/DVConstraint.java
@@ -17,7 +17,6 @@
package org.apache.poi.hssf.usermodel;
-import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -463,7 +462,7 @@ public class DVConstraint implements DataValidationConstraint {
case ValidationType.FORMULA:
return createCustomFormulaConstraint(toFormulaString(dvRecord.getFormula1(), book).string());
default:
- throw new UnsupportedOperationException(MessageFormat.format("validationType={0}", dvRecord.getDataType()));
+ throw new UnsupportedOperationException("validationType="+dvRecord.getDataType());
}
}
diff --git a/src/java/org/apache/poi/hssf/usermodel/DummyGraphics2d.java b/src/java/org/apache/poi/hssf/usermodel/DummyGraphics2d.java
index edb87c862..3baefb691 100644
--- a/src/java/org/apache/poi/hssf/usermodel/DummyGraphics2d.java
+++ b/src/java/org/apache/poi/hssf/usermodel/DummyGraphics2d.java
@@ -34,13 +34,13 @@ import java.util.Map;
public class DummyGraphics2d
extends Graphics2D
{
- BufferedImage img;
+ private BufferedImage bufimg;
private Graphics2D g2D;
public DummyGraphics2d()
{
- img = new BufferedImage(1000, 1000, 2);
- g2D = (Graphics2D)img.getGraphics();
+ bufimg = new BufferedImage(1000, 1000, 2);
+ g2D = (Graphics2D)bufimg.getGraphics();
}
public void addRenderingHints(Map,?> hints)
@@ -710,12 +710,6 @@ public class DummyGraphics2d
return g2D.getClipBounds( r );
}
- @SuppressWarnings("deprecation")
- public Rectangle getClipRect() {
- System.out.println( "getClipRect():" );
- return g2D.getClipRect();
- }
-
public Color getColor()
{
System.out.println( "getColor():" );
diff --git a/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java b/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java
index 1f31e80bd..3bae84894 100644
--- a/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java
+++ b/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java
@@ -20,6 +20,7 @@ package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
+import org.apache.poi.util.SuppressForbidden;
import java.awt.*;
import java.awt.image.ImageObserver;
@@ -57,8 +58,7 @@ import java.text.AttributedCharacterIterator;
* HSSFClientAnchor.getAnchorHeightInPoints().
*
*/
-public class EscherGraphics
- extends Graphics
+public class EscherGraphics extends Graphics
{
private HSSFShapeGroup escherGroup;
private HSSFWorkbook workbook;
@@ -293,18 +293,18 @@ public class EscherGraphics
textbox.setString( s );
}
- private HSSFFont matchFont( Font font )
+ private HSSFFont matchFont( Font matchFont )
{
HSSFColor hssfColor = workbook.getCustomPalette()
.findColor((byte)foreground.getRed(), (byte)foreground.getGreen(), (byte)foreground.getBlue());
if (hssfColor == null)
hssfColor = workbook.getCustomPalette().findSimilarColor((byte)foreground.getRed(), (byte)foreground.getGreen(), (byte)foreground.getBlue());
- boolean bold = (font.getStyle() & Font.BOLD) != 0;
- boolean italic = (font.getStyle() & Font.ITALIC) != 0;
+ boolean bold = (matchFont.getStyle() & Font.BOLD) != 0;
+ boolean italic = (matchFont.getStyle() & Font.ITALIC) != 0;
HSSFFont hssfFont = workbook.findFont(bold ? HSSFFont.BOLDWEIGHT_BOLD : 0,
hssfColor.getIndex(),
- (short)(font.getSize() * 20),
- font.getName(),
+ (short)(matchFont.getSize() * 20),
+ matchFont.getName(),
italic,
false,
(short)0,
@@ -314,8 +314,8 @@ public class EscherGraphics
hssfFont = workbook.createFont();
hssfFont.setBoldweight(bold ? HSSFFont.BOLDWEIGHT_BOLD : 0);
hssfFont.setColor(hssfColor.getIndex());
- hssfFont.setFontHeight((short)(font.getSize() * 20));
- hssfFont.setFontName(font.getName());
+ hssfFont.setFontHeight((short)(matchFont.getSize() * 20));
+ hssfFont.setFontName(matchFont.getName());
hssfFont.setItalic(italic);
hssfFont.setStrikeout(false);
hssfFont.setTypeOffset((short) 0);
@@ -431,11 +431,6 @@ public class EscherGraphics
return null;
}
- public Rectangle getClipRect()
- {
- return getClipBounds();
- }
-
public Color getColor()
{
return foreground;
@@ -447,6 +442,7 @@ public class EscherGraphics
}
@SuppressWarnings("deprecation")
+ @SuppressForbidden
public FontMetrics getFontMetrics(Font f)
{
return Toolkit.getDefaultToolkit().getFontMetrics(f);
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
index b1e8b7a00..8fbdd1276 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
@@ -52,6 +52,7 @@ import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.NumberToTextConverter;
+import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
@@ -989,7 +990,7 @@ public class HSSFCell implements Cell {
case CELL_TYPE_NUMERIC:
//TODO apply the dataformat for this cell
if (HSSFDateUtil.isCellDateFormatted(this)) {
- DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
+ DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", LocaleUtil.getUserLocale());
return sdf.format(getDateCellValue());
}
return String.valueOf(getNumericCellValue());
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java
index af1243eb0..13abd91e6 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java
@@ -23,6 +23,7 @@ import java.text.SimpleDateFormat;
import java.util.Locale;
import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.util.LocaleUtil;
/**
* HSSFDataFormatter contains methods for formatting the value stored in an
@@ -76,7 +77,7 @@ public final class HSSFDataFormatter extends DataFormatter {
* Creates a formatter using the {@link Locale#getDefault() default locale}.
*/
public HSSFDataFormatter() {
- this(Locale.getDefault());
+ this(LocaleUtil.getUserLocale());
}
}
diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
index 5afb4eb8f..48d75ab94 100644
--- a/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
+++ b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
@@ -19,6 +19,7 @@
package org.apache.poi.poifs.filesystem;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -85,6 +86,22 @@ public class POIFSFileSystem
super(stream);
}
+ /**
+ *
Creates a POIFSFileSystem from a File. This uses less memory than
+ * creating from an InputStream. The File will be opened read-only
+ *
+ *
Note that with this constructor, you will need to call {@link #close()}
+ * when you're done to have the underlying file closed, as the file is
+ * kept open during normal operation to read the data out.
+ *
+ * @param file the File from which to read the data
+ *
+ * @exception IOException on errors reading, or on invalid data
+ */
+ public POIFSFileSystem(File file) throws IOException {
+ super(file);
+ }
+
/**
* Checks that the supplied InputStream (which MUST
* support mark and reset, or be a PushbackInputStream)
diff --git a/src/java/org/apache/poi/ss/format/CellDateFormatter.java b/src/java/org/apache/poi/ss/format/CellDateFormatter.java
index 0e6cfa15b..dcf702c32 100644
--- a/src/java/org/apache/poi/ss/format/CellDateFormatter.java
+++ b/src/java/org/apache/poi/ss/format/CellDateFormatter.java
@@ -24,19 +24,14 @@ import java.util.Calendar;
import java.util.Date;
import java.util.Formatter;
import java.util.Locale;
-import java.util.TimeZone;
import java.util.regex.Matcher;
+import org.apache.poi.util.LocaleUtil;
+
/**
* Formats a date value.
*/
public class CellDateFormatter extends CellFormatter {
- /**
- * Excel doesn't store TimeZone information in the file, so if in doubt,
- * use UTC to perform calculations
- */
- private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
-
private boolean amPmUpper;
private boolean showM;
private boolean showAmPm;
@@ -50,8 +45,7 @@ public class CellDateFormatter extends CellFormatter {
"mm/d/y");
static {
- Calendar c = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
- c.set(1904, 0, 1, 0, 0, 0);
+ Calendar c = LocaleUtil.getLocaleCalendar(1904, 0, 1, 0, 0, 0);
EXCEL_EPOCH_DATE = c.getTime();
EXCEL_EPOCH_TIME = c.getTimeInMillis();
}
diff --git a/src/java/org/apache/poi/ss/format/CellFormatPart.java b/src/java/org/apache/poi/ss/format/CellFormatPart.java
index 9a966e152..40d8c0849 100644
--- a/src/java/org/apache/poi/ss/format/CellFormatPart.java
+++ b/src/java/org/apache/poi/ss/format/CellFormatPart.java
@@ -524,4 +524,8 @@ public class CellFormatPart {
String str = m.group(g);
return (str == null ? "" : str);
}
+
+ public String toString() {
+ return format.format;
+ }
}
diff --git a/src/java/org/apache/poi/ss/format/CellGeneralFormatter.java b/src/java/org/apache/poi/ss/format/CellGeneralFormatter.java
index cb5d4a1bb..cdee8cf01 100644
--- a/src/java/org/apache/poi/ss/format/CellGeneralFormatter.java
+++ b/src/java/org/apache/poi/ss/format/CellGeneralFormatter.java
@@ -57,7 +57,7 @@ public class CellGeneralFormatter extends CellFormatter {
stripZeros = false;
}
- Formatter formatter = new Formatter(toAppendTo);
+ Formatter formatter = new Formatter(toAppendTo, LOCALE);
try {
formatter.format(LOCALE, fmt, value);
} finally {
diff --git a/src/java/org/apache/poi/ss/format/CellNumberFormatter.java b/src/java/org/apache/poi/ss/format/CellNumberFormatter.java
index 2ea72cc69..3addf46fe 100644
--- a/src/java/org/apache/poi/ss/format/CellNumberFormatter.java
+++ b/src/java/org/apache/poi/ss/format/CellNumberFormatter.java
@@ -17,6 +17,7 @@
package org.apache.poi.ss.format;
import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
import java.text.FieldPosition;
import java.util.BitSet;
import java.util.Collections;
@@ -30,6 +31,7 @@ import java.util.TreeSet;
import java.util.regex.Matcher;
import org.apache.poi.ss.format.CellFormatPart.PartHandler;
+import org.apache.poi.util.LocaleUtil;
/**
* This class implements printing out a value using a number format.
@@ -182,8 +184,8 @@ public class CellNumberFormatter extends CellFormatter {
private char insertSignForExponent;
public String handlePart(Matcher m, String part, CellFormatType type,
- StringBuffer desc) {
- int pos = desc.length();
+ StringBuffer descBuf) {
+ int pos = descBuf.length();
char firstCh = part.charAt(0);
switch (firstCh) {
case 'e':
@@ -203,7 +205,7 @@ public class CellNumberFormatter extends CellFormatter {
case '#':
if (insertSignForExponent != '\0') {
specials.add(new Special(insertSignForExponent, pos));
- desc.append(insertSignForExponent);
+ descBuf.append(insertSignForExponent);
insertSignForExponent = '\0';
pos++;
}
@@ -354,7 +356,8 @@ public class CellNumberFormatter extends CellFormatter {
fmtBuf.append('E');
placeZeros(fmtBuf, exponentSpecials.subList(2,
exponentSpecials.size()));
- decimalFmt = new DecimalFormat(fmtBuf.toString());
+ DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(LocaleUtil.getUserLocale());
+ decimalFmt = new DecimalFormat(fmtBuf.toString(), dfs);
}
if (exponent != null)
@@ -594,7 +597,7 @@ public class CellNumberFormatter extends CellFormatter {
writeFraction(value, null, fractional, output, mods);
} else {
StringBuffer result = new StringBuffer();
- Formatter f = new Formatter(result);
+ Formatter f = new Formatter(result, LOCALE);
try {
f.format(LOCALE, printfFmt, value);
} finally {
@@ -767,6 +770,7 @@ public class CellNumberFormatter extends CellFormatter {
writeInteger(exponentNum, output, exponentDigitSpecials, mods, false);
}
+ @SuppressWarnings("unchecked")
private void writeFraction(double value, StringBuffer result,
double fractional, StringBuffer output, Set mods) {
@@ -869,7 +873,7 @@ public class CellNumberFormatter extends CellFormatter {
List numSpecials, Set mods) {
StringBuffer sb = new StringBuffer();
- Formatter formatter = new Formatter(sb);
+ Formatter formatter = new Formatter(sb, LOCALE);
try {
formatter.format(LOCALE, fmt, num);
} finally {
diff --git a/src/java/org/apache/poi/ss/formula/atp/DateParser.java b/src/java/org/apache/poi/ss/formula/atp/DateParser.java
index 73b51a5fb..4ab15888f 100644
--- a/src/java/org/apache/poi/ss/formula/atp/DateParser.java
+++ b/src/java/org/apache/poi/ss/formula/atp/DateParser.java
@@ -18,24 +18,16 @@
package org.apache.poi.ss.formula.atp;
import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
import java.util.regex.Pattern;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
+import org.apache.poi.util.LocaleUtil;
/**
* Parser for java dates.
*/
public class DateParser {
- /**
- * Excel doesn't store TimeZone information in the file, so if in doubt,
- * use UTC to perform calculations
- */
- private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
-
public DateParser instance = new DateParser();
private DateParser() {
@@ -80,10 +72,10 @@ public class DateParser {
return makeDate(f0, f1, f2);
}
// otherwise the format seems to depend on OS settings (default date format)
- if (false) {
- // MM/DD/YYYY is probably a good guess, if the in the US
- return makeDate(f2, f0, f1);
- }
+// if (false) {
+// // MM/DD/YYYY is probably a good guess, if the in the US
+// return makeDate(f2, f0, f1);
+// }
// TODO - find a way to choose the correct date format
throw new RuntimeException("Unable to determine date format for text '" + strVal + "'");
}
@@ -95,9 +87,7 @@ public class DateParser {
if (month < 1 || month > 12) {
throw new EvaluationException(ErrorEval.VALUE_INVALID);
}
- Calendar cal = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT);
- cal.set(year, month - 1, 1, 0, 0, 0);
- cal.set(Calendar.MILLISECOND, 0);
+ Calendar cal = LocaleUtil.getLocaleCalendar(year, month - 1, 1, 0, 0, 0);
if (day < 1 || day > cal.getActualMaximum(Calendar.DAY_OF_MONTH)) {
throw new EvaluationException(ErrorEval.VALUE_INVALID);
}
diff --git a/src/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java b/src/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java
index ada303436..29b29feaa 100644
--- a/src/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java
+++ b/src/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java
@@ -19,21 +19,14 @@ package org.apache.poi.ss.formula.atp;
import java.util.Calendar;
import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.util.LocaleUtil;
/**
* A calculator for workdays, considering dates as excel representations.
*/
public class WorkdayCalculator {
- /**
- * Excel doesn't store TimeZone information in the file, so if in doubt,
- * use UTC to perform calculations
- */
- private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
-
public static final WorkdayCalculator instance = new WorkdayCalculator();
/**
@@ -69,7 +62,7 @@ public class WorkdayCalculator {
public Date calculateWorkdays(double start, int workdays, double[] holidays) {
Date startDate = DateUtil.getJavaDate(start);
int direction = workdays < 0 ? -1 : 1;
- Calendar endDate = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
+ Calendar endDate = LocaleUtil.getLocaleCalendar();
endDate.setTime(startDate);
double excelEndDate = DateUtil.getExcelDate(endDate.getTime());
while (workdays != 0) {
@@ -97,7 +90,7 @@ public class WorkdayCalculator {
int startDay = (int) Math.floor(start < end ? start : end);
int endDay = (int) Math.floor(end > start ? end : start);
for (; startDay <= endDay; startDay++) {
- Calendar today = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
+ Calendar today = LocaleUtil.getLocaleCalendar();
today.setTime(DateUtil.getJavaDate(startDay));
if (today.get(Calendar.DAY_OF_WEEK) == dayOfWeek) {
pastDaysOfWeek++;
@@ -133,7 +126,7 @@ public class WorkdayCalculator {
* @return true if date is weekend, false otherwise.
*/
protected boolean isWeekend(double aDate) {
- Calendar date = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
+ Calendar date = LocaleUtil.getLocaleCalendar();
date.setTime(DateUtil.getJavaDate(aDate));
return date.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || date.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
}
diff --git a/src/java/org/apache/poi/ss/formula/atp/YearFracCalculator.java b/src/java/org/apache/poi/ss/formula/atp/YearFracCalculator.java
index d9dc068d4..42bd9aed1 100644
--- a/src/java/org/apache/poi/ss/formula/atp/YearFracCalculator.java
+++ b/src/java/org/apache/poi/ss/formula/atp/YearFracCalculator.java
@@ -18,13 +18,11 @@
package org.apache.poi.ss.formula.atp;
import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.util.LocaleUtil;
/**
@@ -35,8 +33,6 @@ import org.apache.poi.ss.usermodel.DateUtil;
* @author Josh Micich
*/
final class YearFracCalculator {
- /** use UTC time-zone to avoid daylight savings issues */
- private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC");
private static final int MS_PER_HOUR = 60 * 60 * 1000;
private static final int MS_PER_DAY = 24 * MS_PER_HOUR;
private static final int DAYS_PER_NORMAL_YEAR = 365;
@@ -317,9 +313,10 @@ final class YearFracCalculator {
}
private static SimpleDate createDate(int dayCount) {
- GregorianCalendar calendar = new GregorianCalendar(UTC_TIME_ZONE, Locale.ROOT);
- DateUtil.setCalendar(calendar, dayCount, 0, false, false);
- return new SimpleDate(calendar);
+ /** use UTC time-zone to avoid daylight savings issues */
+ Calendar cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
+ DateUtil.setCalendar(cal, dayCount, 0, false, false);
+ return new SimpleDate(cal);
}
private static final class SimpleDate {
diff --git a/src/java/org/apache/poi/ss/formula/function/FunctionDataBuilder.java b/src/java/org/apache/poi/ss/formula/function/FunctionDataBuilder.java
index 6109cb7b9..b44a03ef3 100644
--- a/src/java/org/apache/poi/ss/formula/function/FunctionDataBuilder.java
+++ b/src/java/org/apache/poi/ss/formula/function/FunctionDataBuilder.java
@@ -30,16 +30,16 @@ import java.util.Set;
*/
final class FunctionDataBuilder {
private int _maxFunctionIndex;
- private final Map _functionDataByName;
- private final Map _functionDataByIndex;
+ private final Map _functionDataByName;
+ private final Map _functionDataByIndex;
/** stores indexes of all functions with footnotes (i.e. whose definitions might change) */
- private final Set _mutatingFunctionIndexes;
+ private final Set _mutatingFunctionIndexes;
public FunctionDataBuilder(int sizeEstimate) {
_maxFunctionIndex = -1;
- _functionDataByName = new HashMap(sizeEstimate * 3 / 2);
- _functionDataByIndex = new HashMap(sizeEstimate * 3 / 2);
- _mutatingFunctionIndexes = new HashSet();
+ _functionDataByName = new HashMap(sizeEstimate * 3 / 2);
+ _functionDataByIndex = new HashMap(sizeEstimate * 3 / 2);
+ _mutatingFunctionIndexes = new HashSet();
}
public void add(int functionIndex, String functionName, int minParams, int maxParams,
@@ -55,14 +55,14 @@ final class FunctionDataBuilder {
}
// allow function definitions to change only if both previous and the new items have footnotes
FunctionMetadata prevFM;
- prevFM = (FunctionMetadata) _functionDataByName.get(functionName);
+ prevFM = _functionDataByName.get(functionName);
if(prevFM != null) {
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) {
throw new RuntimeException("Multiple entries for function name '" + functionName + "'");
}
_functionDataByIndex.remove(Integer.valueOf(prevFM.getIndex()));
}
- prevFM = (FunctionMetadata) _functionDataByIndex.get(indexKey);
+ prevFM = _functionDataByIndex.get(indexKey);
if(prevFM != null) {
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) {
throw new RuntimeException("Multiple entries for function index (" + functionIndex + ")");
diff --git a/src/java/org/apache/poi/ss/formula/functions/DateFunc.java b/src/java/org/apache/poi/ss/formula/functions/DateFunc.java
index f767d1574..8ab14dc6d 100644
--- a/src/java/org/apache/poi/ss/formula/functions/DateFunc.java
+++ b/src/java/org/apache/poi/ss/formula/functions/DateFunc.java
@@ -27,18 +27,13 @@ import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.util.LocaleUtil;
/**
* Implementation for the Excel function DATE
*/
public final class DateFunc extends Fixed3ArgFunction {
- /**
- * Excel doesn't store TimeZone information in the file, so if in doubt,
- * use UTC to perform calculations
- */
- private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
-
public static final Function instance = new DateFunc();
private DateFunc() {
@@ -91,9 +86,7 @@ public final class DateFunc extends Fixed3ArgFunction {
}
// Turn this into a Java date
- Calendar c = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT);
- c.set(year, month, day, 0, 0, 0);
- c.set(Calendar.MILLISECOND, 0);
+ Calendar c = LocaleUtil.getLocaleCalendar(year, month, day);
// Handle negative days of the week, that pull us across
// the 29th of Feb 1900
diff --git a/src/java/org/apache/poi/ss/formula/functions/Days360.java b/src/java/org/apache/poi/ss/formula/functions/Days360.java
index 83b12dbbb..8dba97656 100644
--- a/src/java/org/apache/poi/ss/formula/functions/Days360.java
+++ b/src/java/org/apache/poi/ss/formula/functions/Days360.java
@@ -17,14 +17,13 @@
package org.apache.poi.ss.formula.functions;
import java.util.Calendar;
-import java.util.Locale;
-import java.util.TimeZone;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.OperandResolver;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.util.LocaleUtil;
/**
*
Calculates the number of days between two dates based on a 360-day year
@@ -67,12 +66,6 @@ import org.apache.poi.ss.usermodel.DateUtil;
* @see DAYS360 Function Produces Different Values Depending on the Version of Excel
*/
public class Days360 extends Var2or3ArgFunction {
- /**
- * Excel doesn't store TimeZone information in the file, so if in doubt,
- * use UTC to perform calculations
- */
- private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
-
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
double result;
try {
@@ -112,8 +105,8 @@ public class Days360 extends Var2or3ArgFunction {
}
private static Calendar getDate(double date) {
- Calendar processedDate = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
- processedDate.setTime(DateUtil.getJavaDate(date, false, DEFAULT_TIMEZONE));
+ Calendar processedDate = LocaleUtil.getLocaleCalendar();
+ processedDate.setTime(DateUtil.getJavaDate(date, false));
return processedDate;
}
diff --git a/src/java/org/apache/poi/ss/formula/functions/Dec2Hex.java b/src/java/org/apache/poi/ss/formula/functions/Dec2Hex.java
index caf92bb33..54a624652 100644
--- a/src/java/org/apache/poi/ss/formula/functions/Dec2Hex.java
+++ b/src/java/org/apache/poi/ss/formula/functions/Dec2Hex.java
@@ -109,7 +109,7 @@ public final class Dec2Hex extends Var1or2ArgFunction implements FreeRefFunction
String hex;
if (placesNumber != 0) {
- hex = String.format("%0"+placesNumber+"X", number1.intValue(), Locale.ROOT);
+ hex = String.format(Locale.ROOT, "%0"+placesNumber+"X", number1.intValue());
}
else {
hex = Integer.toHexString(number1.intValue());
diff --git a/src/java/org/apache/poi/ss/formula/functions/EDate.java b/src/java/org/apache/poi/ss/formula/functions/EDate.java
index 205879fed..dcfd704f1 100644
--- a/src/java/org/apache/poi/ss/formula/functions/EDate.java
+++ b/src/java/org/apache/poi/ss/formula/functions/EDate.java
@@ -30,17 +30,12 @@ import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.RefEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.util.LocaleUtil;
/**
* Implementation for Excel EDATE () function.
*/
public class EDate implements FreeRefFunction {
- /**
- * Excel doesn't store TimeZone information in the file, so if in doubt,
- * use UTC to perform calculations
- */
- private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
-
public static final FreeRefFunction instance = new EDate();
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
@@ -52,7 +47,7 @@ public class EDate implements FreeRefFunction {
int offsetInMonthAsNumber = (int) getValue(args[1]);
Date startDate = DateUtil.getJavaDate(startDateAsNumber);
- Calendar calendar = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
+ Calendar calendar = LocaleUtil.getLocaleCalendar();
calendar.setTime(startDate);
calendar.add(Calendar.MONTH, offsetInMonthAsNumber);
return new NumberEval(DateUtil.getExcelDate(calendar.getTime()));
diff --git a/src/java/org/apache/poi/ss/formula/functions/EOMonth.java b/src/java/org/apache/poi/ss/formula/functions/EOMonth.java
index 968b67eba..63836e591 100644
--- a/src/java/org/apache/poi/ss/formula/functions/EOMonth.java
+++ b/src/java/org/apache/poi/ss/formula/functions/EOMonth.java
@@ -19,9 +19,6 @@ package org.apache.poi.ss.formula.functions;
import java.util.Calendar;
import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.eval.ErrorEval;
@@ -29,6 +26,7 @@ import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.util.LocaleUtil;
/**
* Implementation for the Excel EOMONTH() function.
@@ -45,12 +43,6 @@ import org.apache.poi.ss.usermodel.DateUtil;
* zero or negative (in the past).
*/
public class EOMonth implements FreeRefFunction {
- /**
- * Excel doesn't store TimeZone information in the file, so if in doubt,
- * use UTC to perform calculations
- */
- private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
-
public static final FreeRefFunction instance = new EOMonth();
@Override
@@ -70,10 +62,13 @@ public class EOMonth implements FreeRefFunction {
Date startDate = DateUtil.getJavaDate(startDateAsNumber, false);
- Calendar cal = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT);
+ Calendar cal = LocaleUtil.getLocaleCalendar();
cal.setTime(startDate);
- cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
- cal.set(Calendar.MILLISECOND, 0);
+ cal.clear(Calendar.HOUR);
+ cal.set(Calendar.HOUR_OF_DAY, 0);
+ cal.clear(Calendar.MINUTE);
+ cal.clear(Calendar.SECOND);
+ cal.clear(Calendar.MILLISECOND);
cal.add(Calendar.MONTH, months + 1);
cal.set(Calendar.DAY_OF_MONTH, 1);
diff --git a/src/java/org/apache/poi/ss/formula/functions/TextFunction.java b/src/java/org/apache/poi/ss/formula/functions/TextFunction.java
index 76c5fa1ba..7cffa1b89 100644
--- a/src/java/org/apache/poi/ss/formula/functions/TextFunction.java
+++ b/src/java/org/apache/poi/ss/formula/functions/TextFunction.java
@@ -36,7 +36,7 @@ import org.apache.poi.ss.usermodel.DataFormatter;
*/
public abstract class TextFunction implements Function {
protected static final DataFormatter formatter = new DataFormatter();
- protected static final String EMPTY_STRING = "";
+ protected static final String EMPTY_STRING = "";
protected static final String evaluateStringArg(ValueEval eval, int srcRow, int srcCol) throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(eval, srcRow, srcCol);
diff --git a/src/java/org/apache/poi/ss/formula/functions/Today.java b/src/java/org/apache/poi/ss/formula/functions/Today.java
index 60cdedb1b..d86844aa2 100644
--- a/src/java/org/apache/poi/ss/formula/functions/Today.java
+++ b/src/java/org/apache/poi/ss/formula/functions/Today.java
@@ -18,28 +18,23 @@
package org.apache.poi.ss.formula.functions;
import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.util.LocaleUtil;
/**
* Implementation of Excel TODAY() Function
*/
public final class Today extends Fixed0ArgFunction {
- /**
- * Excel doesn't store TimeZone information in the file, so if in doubt,
- * use UTC to perform calculations
- */
- private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
-
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
- Calendar now = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT);
- now.set(now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DATE),0,0,0);
- now.set(Calendar.MILLISECOND, 0);
+ Calendar now = LocaleUtil.getLocaleCalendar();
+ now.clear(Calendar.HOUR);
+ now.set(Calendar.HOUR_OF_DAY,0);
+ now.clear(Calendar.MINUTE);
+ now.clear(Calendar.SECOND);
+ now.clear(Calendar.MILLISECOND);
return new NumberEval(DateUtil.getExcelDate(now.getTime()));
}
}
diff --git a/src/java/org/apache/poi/ss/formula/functions/WeekNum.java b/src/java/org/apache/poi/ss/formula/functions/WeekNum.java
index f27ee7e30..888ad11a0 100644
--- a/src/java/org/apache/poi/ss/formula/functions/WeekNum.java
+++ b/src/java/org/apache/poi/ss/formula/functions/WeekNum.java
@@ -17,14 +17,16 @@
package org.apache.poi.ss.formula.functions;
-import org.apache.poi.ss.formula.OperationEvaluationContext;
-import org.apache.poi.ss.formula.eval.*;
-import org.apache.poi.ss.usermodel.DateUtil;
-
import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
+
+import org.apache.poi.ss.formula.OperationEvaluationContext;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.EvaluationException;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.OperandResolver;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.util.LocaleUtil;
/**
* Implementation for Excel WeekNum() function.
@@ -42,12 +44,6 @@ import java.util.TimeZone;
* 2 Week begins on Monday. Weekdays are numbered 1 through 7.
*/
public class WeekNum extends Fixed2ArgFunction implements FreeRefFunction {
- /**
- * Excel doesn't store TimeZone information in the file, so if in doubt,
- * use UTC to perform calculations
- */
- private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
-
public static final FreeRefFunction instance = new WeekNum();
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval serialNumVE, ValueEval returnTypeVE) {
@@ -57,7 +53,7 @@ public class WeekNum extends Fixed2ArgFunction implements FreeRefFunction {
} catch (EvaluationException e) {
return ErrorEval.VALUE_INVALID;
}
- Calendar serialNumCalendar = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT);
+ Calendar serialNumCalendar = LocaleUtil.getLocaleCalendar();
serialNumCalendar.setTime(DateUtil.getJavaDate(serialNum, false));
int returnType = 0;
diff --git a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java
index 6cb9d4d71..cecfd1072 100644
--- a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java
+++ b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java
@@ -36,10 +36,13 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Observable;
+import java.util.Observer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.ss.util.NumberToTextConverter;
+import org.apache.poi.util.LocaleUtil;
/**
@@ -100,7 +103,7 @@ import org.apache.poi.ss.util.NumberToTextConverter;
* Excel will output "", DataFormatter will output "0".
*
*/
-public class DataFormatter {
+public class DataFormatter implements Observer {
private static final String defaultFractionWholePartFormat = "#";
private static final String defaultFractionFractionPartFormat = "#/##";
/** Pattern to find a number format: "0" or "#" */
@@ -153,18 +156,18 @@ public class DataFormatter {
/**
* The decimal symbols of the locale used for formatting values.
*/
- private final DecimalFormatSymbols decimalSymbols;
+ private DecimalFormatSymbols decimalSymbols;
/**
* The date symbols of the locale used for formatting values.
*/
- private final DateFormatSymbols dateSymbols;
+ private DateFormatSymbols dateSymbols;
/** General format for whole numbers. */
- private final Format generalWholeNumFormat;
+ private Format generalWholeNumFormat;
/** General format for decimal numbers. */
- private final Format generalDecimalNumFormat;
+ private Format generalDecimalNumFormat;
/** A default format to use when a number pattern cannot be parsed. */
private Format defaultNumFormat;
@@ -173,15 +176,37 @@ public class DataFormatter {
* A map to cache formats.
* Map formats
*/
- private final Map formats;
+ private final Map formats = new HashMap();
private boolean emulateCsv = false;
+ /** stores the locale valid it the last formatting call */
+ private Locale locale;
+
+ /** stores if the locale should change according to {@link LocaleUtil#getUserLocale()} */
+ private boolean localeIsAdapting = true;
+
+ private class LocaleChangeObservable extends Observable {
+ void checkForLocaleChange() {
+ checkForLocaleChange(LocaleUtil.getUserLocale());
+ }
+ void checkForLocaleChange(Locale newLocale) {
+ if (!localeIsAdapting) return;
+ if (newLocale.equals(locale)) return;
+ super.setChanged();
+ notifyObservers(newLocale);
+ }
+ }
+
+ /** the Observable to notify, when the locale has been changed */
+ private final LocaleChangeObservable localeChangedObervable = new LocaleChangeObservable();
+
/**
* Creates a formatter using the {@link Locale#getDefault() default locale}.
*/
public DataFormatter() {
this(false);
+ this.localeIsAdapting = true;
}
/**
@@ -190,8 +215,8 @@ public class DataFormatter {
* @param emulateCsv whether to emulate CSV output.
*/
public DataFormatter(boolean emulateCsv) {
- this(Locale.getDefault());
- this.emulateCsv = emulateCsv;
+ this(LocaleUtil.getUserLocale(), emulateCsv);
+ this.localeIsAdapting = true;
}
/**
@@ -208,29 +233,9 @@ public class DataFormatter {
* Creates a formatter using the given locale.
*/
public DataFormatter(Locale locale) {
- dateSymbols = new DateFormatSymbols(locale);
- decimalSymbols = new DecimalFormatSymbols(locale);
- generalWholeNumFormat = new DecimalFormat("#", decimalSymbols);
- generalDecimalNumFormat = new DecimalFormat("#.##########", decimalSymbols);
-
- formats = new HashMap();
-
- // init built-in formats
-
- Format zipFormat = ZipPlusFourFormat.instance;
- addFormat("00000\\-0000", zipFormat);
- addFormat("00000-0000", zipFormat);
-
- Format phoneFormat = PhoneFormat.instance;
- // allow for format string variations
- addFormat("[<=9999999]###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
- addFormat("[<=9999999]###-####;(###) ###-####", phoneFormat);
- addFormat("###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
- addFormat("###-####;(###) ###-####", phoneFormat);
-
- Format ssnFormat = SSNFormat.instance;
- addFormat("000\\-00\\-0000", ssnFormat);
- addFormat("000-00-0000", ssnFormat);
+ localeChangedObervable.addObserver(this);
+ localeChangedObervable.checkForLocaleChange(locale);
+ this.localeIsAdapting = false;
}
/**
@@ -260,6 +265,8 @@ public class DataFormatter {
}
private Format getFormat(double cellValue, int formatIndex, String formatStrIn) {
+ localeChangedObervable.checkForLocaleChange();
+
// // Might be better to separate out the n p and z formats, falling back to p when n and z are not set.
// // That however would require other code to be re factored.
// String[] formatBits = formatStrIn.split(";");
@@ -329,6 +336,8 @@ public class DataFormatter {
}
private Format createFormat(double cellValue, int formatIndex, String sFormat) {
+ localeChangedObervable.checkForLocaleChange();
+
String formatStr = sFormat;
// Remove colour formatting if present
@@ -666,6 +675,8 @@ public class DataFormatter {
return getDefaultFormat(cell.getNumericCellValue());
}
private Format getDefaultFormat(double cellValue) {
+ localeChangedObervable.checkForLocaleChange();
+
// for numeric cells try user supplied default
if (defaultNumFormat != null) {
return defaultNumFormat;
@@ -742,6 +753,8 @@ public class DataFormatter {
* @see #formatCellValue(Cell)
*/
public String formatRawCellContents(double value, int formatIndex, String formatString, boolean use1904Windowing) {
+ localeChangedObervable.checkForLocaleChange();
+
// Is it a date?
if(DateUtil.isADateFormat(formatIndex,formatString)) {
if(DateUtil.isValidExcelDate(value)) {
@@ -820,6 +833,7 @@ public class DataFormatter {
* @return a string value of the cell
*/
public String formatCellValue(Cell cell, FormulaEvaluator evaluator) {
+ localeChangedObervable.checkForLocaleChange();
if (cell == null) {
return "";
@@ -927,6 +941,59 @@ public class DataFormatter {
format.setRoundingMode(roundingMode);
}
+ /**
+ * If the Locale has been changed via {@link LocaleUtil#setUserLocale(Locale)} the stored
+ * formats need to be refreshed. All formats which aren't originated from DataFormatter
+ * itself, i.e. all Formats added via {@link DataFormatter#addFormat(String, Format)} and
+ * {@link DataFormatter#setDefaultNumberFormat(Format)}, need to be added again.
+ * To notify callers, the returned {@link Observable} should be used.
+ * The Object in {@link Observer#update(Observable, Object)} is the new Locale.
+ *
+ * @return the listener object, where callers can register themself
+ */
+ public Observable getLocaleChangedObservable() {
+ return localeChangedObervable;
+ }
+
+ /**
+ * Update formats when locale has been changed
+ *
+ * @param observable usually this is our own Observable instance
+ * @param localeObj only reacts on Locale objects
+ */
+ public void update(Observable observable, Object localeObj) {
+ if (!(localeObj instanceof Locale)) return;
+ Locale newLocale = (Locale)localeObj;
+ if (!localeIsAdapting || newLocale.equals(locale)) return;
+
+ locale = newLocale;
+
+ dateSymbols = DateFormatSymbols.getInstance(locale);
+ decimalSymbols = DecimalFormatSymbols.getInstance(locale);
+ generalWholeNumFormat = new DecimalFormat("#", decimalSymbols);
+ generalDecimalNumFormat = new DecimalFormat("#.##########", decimalSymbols);
+
+ // init built-in formats
+
+ formats.clear();
+ Format zipFormat = ZipPlusFourFormat.instance;
+ addFormat("00000\\-0000", zipFormat);
+ addFormat("00000-0000", zipFormat);
+
+ Format phoneFormat = PhoneFormat.instance;
+ // allow for format string variations
+ addFormat("[<=9999999]###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
+ addFormat("[<=9999999]###-####;(###) ###-####", phoneFormat);
+ addFormat("###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
+ addFormat("###-####;(###) ###-####", phoneFormat);
+
+ Format ssnFormat = SSNFormat.instance;
+ addFormat("000\\-00\\-0000", ssnFormat);
+ addFormat("000-00-0000", ssnFormat);
+ }
+
+
+
/**
* Format class for Excel's SSN format. This class mimics Excel's built-in
* SSN formatting.
diff --git a/src/java/org/apache/poi/ss/usermodel/DateUtil.java b/src/java/org/apache/poi/ss/usermodel/DateUtil.java
index 0c3c07283..1613a54f6 100644
--- a/src/java/org/apache/poi/ss/usermodel/DateUtil.java
+++ b/src/java/org/apache/poi/ss/usermodel/DateUtil.java
@@ -20,10 +20,11 @@ package org.apache.poi.ss.usermodel;
import java.util.Calendar;
import java.util.Date;
-import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Pattern;
+import org.apache.poi.util.LocaleUtil;
+
/**
* Contains methods for dealing with Excel dates.
*/
@@ -52,13 +53,6 @@ public class DateUtil {
// elapsed time patterns: [h],[m] and [s]
private static final Pattern date_ptrn4 = Pattern.compile("^\\[([hH]+|[mM]+|[sS]+)\\]");
- /**
- * Excel doesn't store TimeZone information in the file, so if in doubt,
- * use UTC to perform calculations
- */
- private static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone("UTC");
-
-
/**
* Given a Date, converts it into a double representing its internal Excel representation,
* which is the number of days since 1/1/1900. Fractional days represent hours, minutes, and seconds.
@@ -78,7 +72,7 @@ public class DateUtil {
* @param use1904windowing Should 1900 or 1904 date windowing be used?
*/
public static double getExcelDate(Date date, boolean use1904windowing) {
- Calendar calStart = Calendar.getInstance(getUserTimeZone(), Locale.ROOT);
+ Calendar calStart = LocaleUtil.getLocaleCalendar();
calStart.setTime(date); // If date includes hours, minutes, and seconds, set them to 0
return internalGetExcelDate(calStart, use1904windowing);
}
@@ -242,6 +236,9 @@ public class DateUtil {
}
calendar.set(startYear,0, wholeDays + dayAdjust, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, millisecondsInDay);
+ if (calendar.get(Calendar.MILLISECOND) == 0) {
+ calendar.clear(Calendar.MILLISECOND);
+ }
if (roundSeconds) {
calendar.add(Calendar.MILLISECOND, 500);
calendar.clear(Calendar.MILLISECOND);
@@ -281,7 +278,7 @@ public class DateUtil {
* @return Java representation of the date in UTC, or null if date is not a valid Excel date
*/
public static Calendar getJavaCalendarUTC(double date, boolean use1904windowing) {
- return getJavaCalendar(date, use1904windowing, TIMEZONE_UTC, false);
+ return getJavaCalendar(date, use1904windowing, LocaleUtil.TIMEZONE_UTC, false);
}
@@ -314,9 +311,9 @@ public class DateUtil {
int millisecondsInDay = (int)((date - wholeDays) * DAY_MILLISECONDS + 0.5);
Calendar calendar;
if (timeZone != null) {
- calendar = Calendar.getInstance(timeZone, Locale.ROOT);
+ calendar = LocaleUtil.getLocaleCalendar(timeZone);
} else {
- calendar = Calendar.getInstance(getUserTimeZone(), Locale.ROOT); // using default time-zone
+ calendar = LocaleUtil.getLocaleCalendar(); // using default time-zone
}
setCalendar(calendar, wholeDays, millisecondsInDay, use1904windowing, roundSeconds);
return calendar;
@@ -334,13 +331,6 @@ public class DateUtil {
private static ThreadLocal lastFormatString = new ThreadLocal();
private static ThreadLocal lastCachedResult = new ThreadLocal();
- private static ThreadLocal userTimeZone = new ThreadLocal() {
- @Override
- protected TimeZone initialValue() {
- return TIMEZONE_UTC;
- }
- };
-
private static boolean isCached(String formatString, int formatIndex) {
String cachedFormatString = lastFormatString.get();
return cachedFormatString != null && formatIndex == lastFormatIndex.get()
@@ -353,23 +343,6 @@ public class DateUtil {
lastCachedResult.set(Boolean.valueOf(cached));
}
- /**
- * as timezone information is not stored in any format, it can be
- * set before any date calculations take place
- *
- * @param timezone the timezone under which date calculations take place
- */
- public static void setUserTimeZone(TimeZone timezone) {
- userTimeZone.set(timezone);
- }
-
- /**
- * @return the time zone which is used for date calculations
- */
- public static TimeZone getUserTimeZone() {
- return userTimeZone.get();
- }
-
/**
* Given a format ID and its format String, will check to see if the
* format represents a date format or not.
@@ -684,9 +657,7 @@ public class DateUtil {
int month = parseInt(monthStr, "month", 1, 12);
int day = parseInt(dayStr, "day", 1, 31);
- Calendar cal = Calendar.getInstance(getUserTimeZone(), Locale.ROOT);
- cal.set(year, month-1, day, 0, 0, 0);
- cal.set(Calendar.MILLISECOND, 0);
+ Calendar cal = LocaleUtil.getLocaleCalendar(year, month-1, day);
return cal.getTime();
}
private static int parseInt(String strVal, String fieldName, int rangeMax) throws FormatException {
diff --git a/src/java/org/apache/poi/ss/usermodel/ExcelStyleDateFormatter.java b/src/java/org/apache/poi/ss/usermodel/ExcelStyleDateFormatter.java
index fd2b61da3..c075b55b2 100644
--- a/src/java/org/apache/poi/ss/usermodel/ExcelStyleDateFormatter.java
+++ b/src/java/org/apache/poi/ss/usermodel/ExcelStyleDateFormatter.java
@@ -17,6 +17,9 @@
package org.apache.poi.ss.usermodel;
import java.util.*;
+
+import org.apache.poi.util.LocaleUtil;
+
import java.math.RoundingMode;
import java.text.*;
@@ -56,16 +59,15 @@ public class ExcelStyleDateFormatter extends SimpleDateFormat {
DataFormatter.setExcelStyleRoundingMode(format2digits, RoundingMode.DOWN);
DataFormatter.setExcelStyleRoundingMode(format3digit);
DataFormatter.setExcelStyleRoundingMode(format4digits);
+ setTimeZone(LocaleUtil.getUserTimeZone());
}
private double dateToBeFormatted = 0.0;
- public ExcelStyleDateFormatter() {
- super();
- }
+ // no-arg constructor is private because of undefined super call with locale
public ExcelStyleDateFormatter(String pattern) {
- super(processFormatPattern(pattern));
+ super(processFormatPattern(pattern), LocaleUtil.getUserLocale());
}
public ExcelStyleDateFormatter(String pattern,
diff --git a/src/java/org/apache/poi/util/FontMetricsDumper.java b/src/java/org/apache/poi/util/FontMetricsDumper.java
index c974c1e16..96676954a 100644
--- a/src/java/org/apache/poi/util/FontMetricsDumper.java
+++ b/src/java/org/apache/poi/util/FontMetricsDumper.java
@@ -18,7 +18,10 @@
package org.apache.poi.util;
-import java.awt.*;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.GraphicsEnvironment;
+import java.awt.Toolkit;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
@@ -26,6 +29,7 @@ import java.util.Properties;
@SuppressWarnings("deprecation")
public class FontMetricsDumper
{
+ @SuppressForbidden
public static void main( String[] args ) throws IOException
{
diff --git a/src/java/org/apache/poi/util/HexDump.java b/src/java/org/apache/poi/util/HexDump.java
index 3cf2758b6..1357b88f0 100644
--- a/src/java/org/apache/poi/util/HexDump.java
+++ b/src/java/org/apache/poi/util/HexDump.java
@@ -149,14 +149,15 @@ public class HexDump {
chars_read = 16;
}
- buffer.append(String.format(Locale.ROOT, "%08X ", display_offset));
+ buffer.append(xpad(display_offset, 8, ""));
for (int k = 0; k < 16; k++) {
if (k < chars_read) {
- buffer.append(String.format(Locale.ROOT, "%02X ", data[ k + j ]));
+ buffer.append(xpad(data[ k + j ], 2, " "));
} else {
buffer.append(" ");
}
}
+ buffer.append(' ');
for (int k = 0; k < chars_read; k++) {
buffer.append(toAscii(data[ k + j ]));
}
@@ -232,20 +233,19 @@ public class HexDump {
* will be written to a new line
* @return A String representing the array of bytes
*/
- public static String toHex(final byte[] value, final int bytesPerLine)
- {
- final int digits =
- (int) Math.round(Math.log(value.length) / Math.log(10) + 0.5);
- final String formatString = (digits == 0 ? ": %d" : "%0"+digits+"d: ");
- StringBuffer retVal = new StringBuffer();
- retVal.append(String.format(Locale.ROOT, formatString, 0));
- int i = -1;
- for(int x = 0; x < value.length; x++)
- {
- if (++i == bytesPerLine)
- {
+ public static String toHex(final byte[] value, final int bytesPerLine) {
+ if (value.length == 0) {
+ return ": 0";
+ }
+ final int digits = (int) Math.round(Math.log(value.length) / Math.log(10) + 0.5);
+ StringBuilder retVal = new StringBuilder();
+ retVal.append(xpad(0, digits, ""));
+ retVal.append(": ");
+ for(int x=0, i=-1; x < value.length; x++) {
+ if (++i == bytesPerLine) {
retVal.append('\n');
- retVal.append(String.format(Locale.ROOT, formatString, x));
+ retVal.append(xpad(x, digits, ""));
+ retVal.append(": ");
i = 0;
} else if (x>0) {
retVal.append(", ");
@@ -262,7 +262,7 @@ public class HexDump {
* @return The result right padded with 0
*/
public static String toHex(final short value) {
- return String.format(Locale.ROOT, "%04X", value);
+ return xpad(value & 0xFFFF, 4, "");
}
/**
@@ -272,7 +272,7 @@ public class HexDump {
* @return The result right padded with 0
*/
public static String toHex(final byte value) {
- return String.format(Locale.ROOT, "%02X", value);
+ return xpad(value & 0xFF, 2, "");
}
/**
@@ -282,7 +282,7 @@ public class HexDump {
* @return The result right padded with 0
*/
public static String toHex(final int value) {
- return String.format(Locale.ROOT, "%08X", value);
+ return xpad(value & 0xFFFFFFFF, 8, "");
}
/**
@@ -292,7 +292,7 @@ public class HexDump {
* @return The result right padded with 0
*/
public static String toHex(final long value) {
- return String.format(Locale.ROOT, "%016X", value);
+ return xpad(value & 0xFFFFFFFF, 16, "");
}
/**
@@ -336,30 +336,46 @@ public class HexDump {
* @return string of 16 (zero padded) uppercase hex chars and prefixed with '0x'
*/
public static String longToHex(long value) {
- return String.format(Locale.ROOT, "0x%016X", value);
+ return xpad(value, 16, "0x");
}
/**
* @return string of 8 (zero padded) uppercase hex chars and prefixed with '0x'
*/
public static String intToHex(int value) {
- return String.format(Locale.ROOT, "0x%08X", value & 0xFFFFFFFF);
+ return xpad(value & 0xFFFFFFFF, 8, "0x");
}
/**
* @return string of 4 (zero padded) uppercase hex chars and prefixed with '0x'
*/
public static String shortToHex(int value) {
- return String.format(Locale.ROOT, "0x%04X", value & 0xFFFF);
+ return xpad(value & 0xFFFF, 4, "0x");
}
/**
* @return string of 2 (zero padded) uppercase hex chars and prefixed with '0x'
*/
public static String byteToHex(int value) {
- return String.format(Locale.ROOT, "0x%02X", value & 0xFF);
+ return xpad(value & 0xFF, 2, "0x");
}
+ private static String xpad(long value, int pad, String prefix) {
+ String sv = Long.toHexString(value).toUpperCase(Locale.ROOT);
+ int len = sv.length();
+ if ((pad == 0 || len == pad) && "".equals(prefix)) return sv;
+ StringBuilder sb = new StringBuilder(prefix);
+ if (len < pad) {
+ sb.append("0000000000000000", 0, pad-len);
+ sb.append(sv);
+ } else if (len > pad) {
+ sb.append(sv, len-pad, len);
+ } else {
+ sb.append(sv);
+ }
+ return sb.toString();
+ }
+
public static void main(String[] args) throws Exception {
File file = new File(args[0]);
InputStream in = new BufferedInputStream(new FileInputStream(file));
diff --git a/src/java/org/apache/poi/util/LocaleUtil.java b/src/java/org/apache/poi/util/LocaleUtil.java
new file mode 100644
index 000000000..4edd65d18
--- /dev/null
+++ b/src/java/org/apache/poi/util/LocaleUtil.java
@@ -0,0 +1,136 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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 org.apache.poi.util;
+
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * This utility class is used to set locale and time zone settings beside
+ * of the JDK internal {@link java.util.Locale#setDefault(Locale)} and
+ * {@link java.util.TimeZone#setDefault(TimeZone)} methods, because
+ * the locale/time zone specific handling of certain office documents -
+ * maybe for different time zones / locales ... - shouldn't affect
+ * other java components.
+ *
+ * The settings are saved in a {@link java.lang.ThreadLocal},
+ * so they only apply to the current thread and can't be set globally.
+ */
+public class LocaleUtil {
+ /**
+ * Excel doesn't store TimeZone information in the file, so if in doubt,
+ * use UTC to perform calculations
+ */
+ public static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone("UTC");
+
+ private static final ThreadLocal userTimeZone = new ThreadLocal() {
+ @Override
+ @SuppressForbidden
+ protected TimeZone initialValue() {
+ return TimeZone.getDefault();
+ }
+ };
+
+ private static final ThreadLocal userLocale = new ThreadLocal() {
+ @Override
+ @SuppressForbidden
+ protected Locale initialValue() {
+ return Locale.getDefault();
+ }
+ };
+
+ /**
+ * As time zone information is not stored in any format, it can be
+ * set before any date calculations take place.
+ * This setting is specific to the current thread.
+ *
+ * @param timezone the timezone under which date calculations take place
+ */
+ public static void setUserTimeZone(TimeZone timezone) {
+ userTimeZone.set(timezone);
+ }
+
+ /**
+ * @return the time zone which is used for date calculations, defaults to UTC
+ */
+ public static TimeZone getUserTimeZone() {
+ return userTimeZone.get();
+ }
+
+ /**
+ * Sets default user locale.
+ * This setting is specific to the current thread.
+ */
+ public static void setUserLocale(Locale locale) {
+ userLocale.set(locale);
+ }
+
+ /**
+ * @return the default user locale, defaults to {@link Locale#ROOT}
+ */
+ public static Locale getUserLocale() {
+ return userLocale.get();
+ }
+
+ /**
+ * @return a calendar for the user locale and time zone
+ */
+ public static Calendar getLocaleCalendar() {
+ return getLocaleCalendar(getUserTimeZone());
+ }
+
+ /**
+ * Convenience method - month is 0-based as in java.util.Calendar
+ *
+ * @param year
+ * @param month
+ * @param day
+ * @return a calendar for the user locale and time zone, and the given date
+ */
+ public static Calendar getLocaleCalendar(int year, int month, int day) {
+ return getLocaleCalendar(year, month, day, 0, 0, 0);
+ }
+
+ /**
+ * Convenience method - month is 0-based as in java.util.Calendar
+ *
+ * @param year
+ * @param month
+ * @param day
+ * @param hour
+ * @param minute
+ * @param second
+ * @return a calendar for the user locale and time zone, and the given date
+ */
+ public static Calendar getLocaleCalendar(int year, int month, int day, int hour, int minute, int second) {
+ Calendar cal = getLocaleCalendar();
+ cal.set(year, month, day, hour, minute, second);
+ cal.clear(Calendar.MILLISECOND);
+ return cal;
+ }
+
+ /**
+ * @return a calendar for the user locale and time zone
+ */
+ public static Calendar getLocaleCalendar(TimeZone timeZone) {
+ return Calendar.getInstance(timeZone, getUserLocale());
+ }
+}
+
diff --git a/src/java/org/apache/poi/util/SuppressForbidden.java b/src/java/org/apache/poi/util/SuppressForbidden.java
new file mode 100644
index 000000000..81891e0c6
--- /dev/null
+++ b/src/java/org/apache/poi/util/SuppressForbidden.java
@@ -0,0 +1,32 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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 org.apache.poi.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/*
+ * Marking class for elements to be ignored by the forbidden apis check
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface SuppressForbidden {
+
+}
diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java
index 523cdeca6..3b917a6fb 100644
--- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java
+++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java
@@ -22,8 +22,7 @@ import java.io.OutputStream;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
-
-import java.util.TimeZone;
+import java.util.Locale;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
@@ -33,6 +32,7 @@ import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageProperties;
import org.apache.poi.openxml4j.util.Nullable;
+import org.apache.poi.util.LocaleUtil;
/**
* Represents the core properties part of a package.
@@ -559,9 +559,8 @@ public final class PackagePropertiesPart extends PackagePart implements
if (s == null || s.equals("")) {
return new Nullable();
}
- SimpleDateFormat df = new SimpleDateFormat(
- "yyyy-MM-dd'T'HH:mm:ss'Z'");
- df.setTimeZone(TimeZone.getTimeZone("UTC"));
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
+ df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
Date d = df.parse(s, new ParsePosition(0));
if (d == null) {
throw new InvalidFormatException("Date not well formated");
@@ -586,9 +585,8 @@ public final class PackagePropertiesPart extends PackagePart implements
return "";
}
- SimpleDateFormat df = new SimpleDateFormat(
- "yyyy-MM-dd'T'HH:mm:ss'Z'");
- df.setTimeZone(TimeZone.getTimeZone("UTC"));
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
+ df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
return df.format(date);
}
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
index 59ae52a20..ab3aa070e 100644
--- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
+++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
@@ -31,6 +31,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;
@@ -196,7 +197,7 @@ public class OOXMLSignatureFacet extends SignatureFacet {
/*
* SignatureTime
*/
- DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+ DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
String nowStr = fmt.format(signatureConfig.getExecutionTime());
LOG.log(POILogger.DEBUG, "now: " + nowStr);
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java
index c14fb3834..5441d58bb 100644
--- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java
+++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java
@@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
@@ -115,8 +116,7 @@ public class XAdESSignatureFacet extends SignatureFacet {
SignedSignaturePropertiesType signedSignatureProperties = signedProperties.addNewSignedSignatureProperties();
// SigningTime
- Calendar xmlGregorianCalendar = Calendar.getInstance();
- xmlGregorianCalendar.setTimeZone(TimeZone.getTimeZone("Z"));
+ Calendar xmlGregorianCalendar = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT);
xmlGregorianCalendar.setTime(signatureConfig.getExecutionTime());
xmlGregorianCalendar.clear(Calendar.MILLISECOND);
signedSignatureProperties.setSigningTime(xmlGregorianCalendar);
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java
index 1a1ac1839..136f3e0eb 100644
--- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java
+++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java
@@ -39,6 +39,8 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
import java.util.UUID;
import javax.xml.crypto.MarshalException;
@@ -214,7 +216,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
CRLIdentifierType crlIdentifier = crlRef.addNewCRLIdentifier();
String issuerName = crl.getIssuerDN().getName().replace(",", ", ");
crlIdentifier.setIssuer(issuerName);
- Calendar cal = Calendar.getInstance();
+ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT);
cal.setTime(crl.getThisUpdate());
crlIdentifier.setIssueTime(cal);
crlIdentifier.setNumber(getCrlNumber(crl));
@@ -238,7 +240,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
BasicOCSPResp basicOcspResp = (BasicOCSPResp)ocspResp.getResponseObject();
- Calendar cal = Calendar.getInstance();
+ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT);
cal.setTime(basicOcspResp.getProducedAt());
ocspIdentifier.setProducedAt(cal);
diff --git a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
index cc59f04fd..9318a0894 100644
--- a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
+++ b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
@@ -26,6 +26,7 @@ import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import javax.imageio.ImageIO;
@@ -155,7 +156,7 @@ public class PPTX2PNG {
// save the result
if (!"null".equals(format)) {
String outname = file.getName().replaceFirst(".pptx?", "");
- outname = String.format("%1$s-%2$04d.%3$s", outname, slideNo, format);
+ outname = String.format(Locale.ROOT, "%1$s-%2$04d.%3$s", outname, slideNo, format);
File outfile = new File(outdir, outname);
ImageIO.write(img, format, outfile);
}
diff --git a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java
index d608f9615..b55360200 100644
--- a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java
+++ b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java
@@ -25,6 +25,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Vector;
@@ -314,7 +315,7 @@ public class XSSFExportToXml implements Comparator{
}
private String getFormattedDate(XSSFCell cell) {
- DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT);
return sdf.format(cell.getDateCellValue());
}
diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java
index c95430bfc..e88667f47 100644
--- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java
+++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java
@@ -35,6 +35,7 @@ import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.xssf.usermodel.XSSFHyperlink;
@@ -653,7 +654,7 @@ public class SXSSFCell implements Cell {
return getCellFormula();
case CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(this)) {
- DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
+ DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", LocaleUtil.getUserLocale());
return sdf.format(getDateCellValue());
}
return getNumericCellValue() + "";
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
index bb57f65c6..0e2c9c549 100644
--- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
+++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
@@ -21,6 +21,7 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
+import java.util.Locale;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.FormulaParser;
@@ -840,7 +841,7 @@ public final class XSSFCell implements Cell {
return getCellFormula();
case CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(this)) {
- DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
+ DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.ROOT);
return sdf.format(getDateCellValue());
}
return Double.toString(getNumericCellValue());
diff --git a/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java b/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
index e18554302..61e57362c 100644
--- a/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
+++ b/src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
@@ -17,37 +17,49 @@
package org.apache.poi;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
-
-import junit.framework.TestCase;
import org.apache.poi.POIXMLProperties.CoreProperties;
import org.apache.poi.openxml4j.util.Nullable;
+import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.XWPFTestDataSamples;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
/**
* Test setting extended and custom OOXML properties
*/
-public final class TestPOIXMLProperties extends TestCase {
+public final class TestPOIXMLProperties {
+ private XWPFDocument sampleDoc;
private POIXMLProperties _props;
private CoreProperties _coreProperties;
+ @Before
public void setUp() throws IOException {
- XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("documentProperties.docx");
+ sampleDoc = XWPFTestDataSamples.openSampleDocument("documentProperties.docx");
_props = sampleDoc.getProperties();
_coreProperties = _props.getCoreProperties();
assertNotNull(_props);
}
+
+ @After
+ public void closeResources() throws Exception {
+ sampleDoc.close();
+ }
- public void testWorkbookExtendedProperties() {
+ @Test
+ public void testWorkbookExtendedProperties() throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook();
POIXMLProperties props = workbook.getProperties();
assertNotNull(props);
@@ -71,7 +83,7 @@ public final class TestPOIXMLProperties extends TestCase {
XSSFWorkbook newWorkbook =
XSSFTestDataSamples.writeOutAndReadBack(workbook);
-
+ workbook.close();
assertTrue(workbook != newWorkbook);
@@ -88,16 +100,19 @@ public final class TestPOIXMLProperties extends TestCase {
assertEquals(application, newCtProps.getApplication());
assertEquals(appVersion, newCtProps.getAppVersion());
+
+ newWorkbook.close();
}
/**
* Test usermodel API for setting custom properties
*/
- public void testCustomProperties() {
- POIXMLDocument wb = new XSSFWorkbook();
+ @Test
+ public void testCustomProperties() throws Exception {
+ POIXMLDocument wb1 = new XSSFWorkbook();
- POIXMLProperties.CustomProperties customProps = wb.getProperties().getCustomProperties();
+ POIXMLProperties.CustomProperties customProps = wb1.getProperties().getCustomProperties();
customProps.addProperty("test-1", "string val");
customProps.addProperty("test-2", 1974);
customProps.addProperty("test-3", 36.6);
@@ -110,9 +125,10 @@ public final class TestPOIXMLProperties extends TestCase {
}
customProps.addProperty("test-4", true);
- wb = XSSFTestDataSamples.writeOutAndReadBack((XSSFWorkbook)wb);
+ POIXMLDocument wb2 = XSSFTestDataSamples.writeOutAndReadBack((XSSFWorkbook)wb1);
+ wb1.close();
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties ctProps =
- wb.getProperties().getCustomProperties().getUnderlyingProperties();
+ wb2.getProperties().getCustomProperties().getUnderlyingProperties();
assertEquals(4, ctProps.sizeOfPropertyArray());
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty p;
@@ -131,7 +147,7 @@ public final class TestPOIXMLProperties extends TestCase {
p = ctProps.getPropertyArray(2);
assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
assertEquals("test-3", p.getName());
- assertEquals(36.6, p.getR8());
+ assertEquals(36.6, p.getR8(), 0);
assertEquals(4, p.getPid());
p = ctProps.getPropertyArray(3);
@@ -139,9 +155,12 @@ public final class TestPOIXMLProperties extends TestCase {
assertEquals("test-4", p.getName());
assertEquals(true, p.getBool());
assertEquals(5, p.getPid());
+
+ wb2.close();
}
- public void testDocumentProperties() {
+ @Test
+ public void testDocumentProperties() {
String category = _coreProperties.getCategory();
assertEquals("test", category);
String contentStatus = "Draft";
@@ -158,21 +177,25 @@ public final class TestPOIXMLProperties extends TestCase {
assertEquals("Hello World", title);
}
- public void testTransitiveSetters() throws IOException {
+ @Test
+ public void testTransitiveSetters() throws IOException {
XWPFDocument doc = new XWPFDocument();
CoreProperties cp = doc.getProperties().getCoreProperties();
- Date dateCreated = new GregorianCalendar(2010, 6, 15, 10, 0, 0).getTime();
+
+ Date dateCreated = LocaleUtil.getLocaleCalendar(2010, 6, 15, 10, 0, 0).getTime();
cp.setCreated(new Nullable(dateCreated));
assertEquals(dateCreated.toString(), cp.getCreated().toString());
- doc = XWPFTestDataSamples.writeOutAndReadBack(doc);
+ XWPFDocument doc2 = XWPFTestDataSamples.writeOutAndReadBack(doc);
+ doc.close();
cp = doc.getProperties().getCoreProperties();
Date dt3 = cp.getCreated();
assertEquals(dateCreated.toString(), dt3.toString());
-
+ doc2.close();
}
+ @Test
public void testGetSetRevision() {
String revision = _coreProperties.getRevision();
assertTrue("Revision number is 1", Integer.parseInt(revision) > 1);
@@ -183,7 +206,7 @@ public final class TestPOIXMLProperties extends TestCase {
}
public static boolean dateTimeEqualToUTCString(Date dateTime, String utcString) {
- Calendar utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.UK);
+ Calendar utcCalendar = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
utcCalendar.setTimeInMillis(dateTime.getTime());
String dateTimeUtcString = utcCalendar.get(Calendar.YEAR) + "-" +
zeroPad((utcCalendar.get(Calendar.MONTH)+1)) + "-" +
diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageCoreProperties.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageCoreProperties.java
index ddc36af0b..bbc53d6b9 100644
--- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageCoreProperties.java
+++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageCoreProperties.java
@@ -17,111 +17,97 @@
package org.apache.poi.openxml4j.opc;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.IOException;
import java.io.InputStream;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
-import java.util.TimeZone;
-
-import junit.framework.TestCase;
+import java.util.Locale;
import org.apache.poi.POIDataSamples;
import org.apache.poi.openxml4j.OpenXML4JTestDataSamples;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.util.Nullable;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
+import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.Test;
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;
-public final class TestPackageCoreProperties extends TestCase {
- private static final POILogger logger = POILogFactory.getLogger(TestPackageCoreProperties.class);
-
+public final class TestPackageCoreProperties {
/**
* Test package core properties getters.
*/
- public void testGetProperties() {
- try {
- // Open the package
- OPCPackage p = OPCPackage.open(OpenXML4JTestDataSamples.openSampleStream("TestPackageCoreProperiesGetters.docx"));
- compareProperties(p);
- p.revert();
- } catch (OpenXML4JException e) {
- logger.log(POILogger.DEBUG, e.getMessage());
- throw new RuntimeException(e);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ @Test
+ public void testGetProperties() throws Exception {
+ // Open the package
+ @SuppressWarnings("resource")
+ OPCPackage p = OPCPackage.open(OpenXML4JTestDataSamples.openSampleStream("TestPackageCoreProperiesGetters.docx"));
+ compareProperties(p);
+ p.revert();
}
/**
* Test package core properties setters.
*/
- public void testSetProperties() throws Exception {
+ @Test
+ public void testSetProperties() throws Exception {
String inputPath = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCoreProperiesSetters.docx");
File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageCoreProperiesSettersOUTPUT.docx");
// Open package
- OPCPackage p = OPCPackage.open(inputPath, PackageAccess.READ_WRITE);
- try {
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
- df.setTimeZone(TimeZone.getTimeZone("UTC"));
- Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition(
- 0));
-
- PackageProperties props = p.getPackageProperties();
- props.setCategoryProperty("MyCategory");
- props.setContentStatusProperty("MyContentStatus");
- props.setContentTypeProperty("MyContentType");
- props.setCreatedProperty(new Nullable(dateToInsert));
- props.setCreatorProperty("MyCreator");
- props.setDescriptionProperty("MyDescription");
- props.setIdentifierProperty("MyIdentifier");
- props.setKeywordsProperty("MyKeywords");
- props.setLanguageProperty("MyLanguage");
- props.setLastModifiedByProperty("Julien Chable");
- props.setLastPrintedProperty(new Nullable(dateToInsert));
- props.setModifiedProperty(new Nullable(dateToInsert));
- props.setRevisionProperty("2");
- props.setTitleProperty("MyTitle");
- props.setSubjectProperty("MySubject");
- props.setVersionProperty("2");
- // Save the package in the output directory
- p.save(outputFile);
-
- // Open the newly created file to check core properties saved values.
- OPCPackage p2 = OPCPackage.open(outputFile.getAbsolutePath(), PackageAccess.READ);
- try {
- compareProperties(p2);
- p2.revert();
- } finally {
- p2.close();
- }
- outputFile.delete();
- } finally {
- // use revert to not re-write the input file
- p.revert();
- }
+ @SuppressWarnings("resource")
+ OPCPackage p = OPCPackage.open(inputPath, PackageAccess.READ_WRITE);
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
+ df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
+ Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0));
+
+ PackageProperties props = p.getPackageProperties();
+ props.setCategoryProperty("MyCategory");
+ props.setContentStatusProperty("MyContentStatus");
+ props.setContentTypeProperty("MyContentType");
+ props.setCreatedProperty(new Nullable(dateToInsert));
+ props.setCreatorProperty("MyCreator");
+ props.setDescriptionProperty("MyDescription");
+ props.setIdentifierProperty("MyIdentifier");
+ props.setKeywordsProperty("MyKeywords");
+ props.setLanguageProperty("MyLanguage");
+ props.setLastModifiedByProperty("Julien Chable");
+ props.setLastPrintedProperty(new Nullable(dateToInsert));
+ props.setModifiedProperty(new Nullable(dateToInsert));
+ props.setRevisionProperty("2");
+ props.setTitleProperty("MyTitle");
+ props.setSubjectProperty("MySubject");
+ props.setVersionProperty("2");
+ // Save the package in the output directory
+ p.save(outputFile);
+ p.revert();
+
+ // Open the newly created file to check core properties saved values.
+ @SuppressWarnings("resource")
+ OPCPackage p2 = OPCPackage.open(outputFile.getAbsolutePath(), PackageAccess.READ);
+ compareProperties(p2);
+ p2.revert();
+ outputFile.delete();
}
private void compareProperties(OPCPackage p) throws InvalidFormatException {
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
- df.setTimeZone(TimeZone.getTimeZone("UTC"));
- Date expectedDate = df.parse("2007-05-12T08:00:00Z", new ParsePosition(
- 0));
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
+ df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
+ Date expectedDate = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0));
// Gets the core properties
PackageProperties props = p.getPackageProperties();
assertEquals("MyCategory", props.getCategoryProperty().getValue());
- assertEquals("MyContentStatus", props.getContentStatusProperty()
- .getValue());
+ assertEquals("MyContentStatus", props.getContentStatusProperty().getValue());
assertEquals("MyContentType", props.getContentTypeProperty().getValue());
assertEquals(expectedDate, props.getCreatedProperty().getValue());
assertEquals("MyCreator", props.getCreatorProperty().getValue());
@@ -129,8 +115,7 @@ public final class TestPackageCoreProperties extends TestCase {
assertEquals("MyIdentifier", props.getIdentifierProperty().getValue());
assertEquals("MyKeywords", props.getKeywordsProperty().getValue());
assertEquals("MyLanguage", props.getLanguageProperty().getValue());
- assertEquals("Julien Chable", props.getLastModifiedByProperty()
- .getValue());
+ assertEquals("Julien Chable", props.getLastModifiedByProperty().getValue());
assertEquals(expectedDate, props.getLastPrintedProperty().getValue());
assertEquals(expectedDate, props.getModifiedProperty().getValue());
assertEquals("2", props.getRevisionProperty().getValue());
@@ -139,9 +124,10 @@ public final class TestPackageCoreProperties extends TestCase {
assertEquals("2", props.getVersionProperty().getValue());
}
- public void testCoreProperties_bug51374() throws Exception {
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
- df.setTimeZone(TimeZone.getTimeZone("UTC"));
+ @Test
+ public void testCoreProperties_bug51374() throws Exception {
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
+ df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
String strDate = "2007-05-12T08:00:00Z";
Date date = df.parse(strDate);
@@ -197,7 +183,8 @@ public final class TestPackageCoreProperties extends TestCase {
pkg.close();
}
- public void testGetPropertiesLO() throws Exception {
+ @Test
+ public void testGetPropertiesLO() throws Exception {
// Open the package
OPCPackage pkg1 = OPCPackage.open(OpenXML4JTestDataSamples.openSampleStream("51444.xlsx"));
PackageProperties props1 = pkg1.getPackageProperties();
@@ -206,13 +193,16 @@ public final class TestPackageCoreProperties extends TestCase {
ByteArrayOutputStream out = new ByteArrayOutputStream();
pkg1.save(out);
out.close();
+ pkg1.close();
OPCPackage pkg2 = OPCPackage.open(new ByteArrayInputStream(out.toByteArray()));
PackageProperties props2 = pkg2.getPackageProperties();
props2.setTitleProperty("Bug 51444 fixed");
+ pkg2.close();
}
- public void testEntitiesInCoreProps_56164() throws Exception {
+ @Test
+ public void testEntitiesInCoreProps_56164() throws Exception {
InputStream is = OpenXML4JTestDataSamples.openSampleStream("CorePropertiesHasEntities.ooxml");
OPCPackage p = OPCPackage.open(is);
is.close();
@@ -236,9 +226,12 @@ public final class TestPackageCoreProperties extends TestCase {
// Check
assertEquals("Stefan Kopf", props.getCreatorProperty().getValue());
+
+ p.close();
}
- public void testListOfCustomProperties() throws Exception {
+ @Test
+ public void testListOfCustomProperties() throws Exception {
File inp = POIDataSamples.getSpreadSheetInstance().getFile("ExcelWithAttachments.xlsm");
OPCPackage pkg = OPCPackage.open(inp, PackageAccess.READ);
XSSFWorkbook wb = new XSSFWorkbook(pkg);
diff --git a/src/ooxml/testcases/org/apache/poi/ss/format/TestCellFormatPart.java b/src/ooxml/testcases/org/apache/poi/ss/format/TestCellFormatPart.java
index 9fd6664ad..7d1952577 100644
--- a/src/ooxml/testcases/org/apache/poi/ss/format/TestCellFormatPart.java
+++ b/src/ooxml/testcases/org/apache/poi/ss/format/TestCellFormatPart.java
@@ -16,14 +16,36 @@
==================================================================== */
package org.apache.poi.ss.format;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.xssf.XSSFITestDataProvider;
+import static org.junit.Assert.assertEquals;
+import java.util.Locale;
+import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.util.LocaleUtil;
+import org.apache.poi.xssf.XSSFITestDataProvider;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
/** Test the individual CellFormatPart types. */
public class TestCellFormatPart extends CellFormatTestBase {
+
+ private static Locale userLocale;
+
+ @BeforeClass
+ public static void setLocale() {
+ userLocale = LocaleUtil.getUserLocale();
+ LocaleUtil.setUserLocale(Locale.ROOT);
+ }
+
+ @AfterClass
+ public static void unsetLocale() {
+ LocaleUtil.setUserLocale(userLocale);
+ }
+
private static final Pattern NUMBER_EXTRACT_FMT = Pattern.compile(
"([-+]?[0-9]+)(\\.[0-9]+)?.*(?:(e).*?([+-]?[0-9]+))",
Pattern.CASE_INSENSITIVE);
@@ -32,6 +54,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
super(XSSFITestDataProvider.instance);
}
+ @Test
public void testGeneralFormat() throws Exception {
runFormatTests("GeneralFormatTests.xlsx", new CellValue() {
public Object getValue(Cell cell) {
@@ -54,6 +77,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
});
}
+ @Test
public void testNumberApproxFormat() throws Exception {
runFormatTests("NumberFormatApproxTests.xlsx", new CellValue() {
public Object getValue(Cell cell) {
@@ -73,14 +97,22 @@ public class TestCellFormatPart extends CellFormatTestBase {
});
}
+ @Test
public void testDateFormat() throws Exception {
- runFormatTests("DateFormatTests.xlsx", new CellValue() {
- public Object getValue(Cell cell) {
- return cell.getDateCellValue();
- }
- });
+ TimeZone tz = LocaleUtil.getUserTimeZone();
+ LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
+ try {
+ runFormatTests("DateFormatTests.xlsx", new CellValue() {
+ public Object getValue(Cell cell) {
+ return cell.getDateCellValue();
+ }
+ });
+ } finally {
+ LocaleUtil.setUserTimeZone(tz);
+ }
}
+ @Test
public void testElapsedFormat() throws Exception {
runFormatTests("ElapsedFormatTests.xlsx", new CellValue() {
public Object getValue(Cell cell) {
@@ -89,6 +121,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
});
}
+ @Test
public void testTextFormat() throws Exception {
runFormatTests("TextFormatTests.xlsx", new CellValue() {
public Object getValue(Cell cell) {
@@ -100,6 +133,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
});
}
+ @Test
public void testConditions() throws Exception {
runFormatTests("FormatConditionTests.xlsx", new CellValue() {
Object getValue(Cell cell) {
diff --git a/src/ooxml/testcases/org/apache/poi/ss/usermodel/BaseTestXCell.java b/src/ooxml/testcases/org/apache/poi/ss/usermodel/BaseTestXCell.java
index f78819ca3..947ab212d 100644
--- a/src/ooxml/testcases/org/apache/poi/ss/usermodel/BaseTestXCell.java
+++ b/src/ooxml/testcases/org/apache/poi/ss/usermodel/BaseTestXCell.java
@@ -17,13 +17,13 @@
package org.apache.poi.ss.usermodel;
+import static org.junit.Assert.assertEquals;
+
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.ss.ITestDataProvider;
-import org.apache.poi.ss.SpreadsheetVersion;
-import org.apache.poi.xssf.SXSSFITestDataProvider;
-import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.junit.Test;
/**
* Class for combined testing of XML-specific functionality of
@@ -37,6 +37,7 @@ public abstract class BaseTestXCell extends BaseTestCell {
super(testDataProvider);
}
+ @Test
public void testXmlEncoding(){
Workbook wb = _testDataProvider.createWorkbook();
Sheet sh = wb.createSheet();
diff --git a/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFCell.java b/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFCell.java
index 25f1d1917..9daf0ccb1 100644
--- a/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFCell.java
+++ b/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFCell.java
@@ -19,6 +19,8 @@
package org.apache.poi.xssf.streaming;
+import static org.junit.Assert.assertEquals;
+
import java.io.IOException;
import javax.xml.namespace.QName;
@@ -30,6 +32,8 @@ import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.xmlbeans.XmlCursor;
+import org.junit.AfterClass;
+import org.junit.Test;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
/**
@@ -42,11 +46,12 @@ public class TestSXSSFCell extends BaseTestXCell {
super(SXSSFITestDataProvider.instance);
}
- @Override
- public void tearDown(){
+ @AfterClass
+ public static void tearDown(){
SXSSFITestDataProvider.instance.cleanup();
}
+ @Test
public void testPreserveSpaces() throws IOException {
String[] samplesWithSpaces = {
" POI",
diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestFormulaEvaluatorOnXSSF.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestFormulaEvaluatorOnXSSF.java
index 1b680d24e..dd966bddc 100644
--- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestFormulaEvaluatorOnXSSF.java
+++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestFormulaEvaluatorOnXSSF.java
@@ -17,14 +17,18 @@
package org.apache.poi.xssf.usermodel;
-import java.io.InputStream;
-import java.io.PrintStream;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
-import junit.framework.Assert;
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Locale;
import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.formula.eval.TestFormulasFromSpreadsheet;
import org.apache.poi.ss.formula.functions.TestMathX;
import org.apache.poi.ss.usermodel.Cell;
@@ -32,7 +36,13 @@ import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.util.LocaleUtil;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
/**
* Performs much the same role as {@link TestFormulasFromSpreadsheet},
@@ -44,206 +54,127 @@ import org.apache.poi.openxml4j.opc.OPCPackage;
* Excel 2007, and re-save it as FormulaEvalTestData_Copy.xlsx
*
*/
-public final class TestFormulaEvaluatorOnXSSF extends TestCase {
-
- private static final class Result {
- public static final int SOME_EVALUATIONS_FAILED = -1;
- public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
- public static final int NO_EVALUATIONS_FOUND = 0;
- }
+@RunWith(Parameterized.class)
+public final class TestFormulaEvaluatorOnXSSF {
+ private static XSSFWorkbook workbook;
+ private static Sheet sheet;
+ private static FormulaEvaluator evaluator;
+ private static Locale userLocale;
+
/**
* This class defines constants for navigating around the test data spreadsheet used for these tests.
*/
- private static final class SS {
+ private static interface SS {
/**
* Name of the test spreadsheet (found in the standard test data folder)
*/
- public final static String FILENAME = "FormulaEvalTestData_Copy.xlsx";
+ String FILENAME = "FormulaEvalTestData_Copy.xlsx";
/**
* Row (zero-based) in the test spreadsheet where the operator examples start.
*/
- public static final int START_OPERATORS_ROW_INDEX = 22; // Row '23'
+ int START_OPERATORS_ROW_INDEX = 22; // Row '23'
/**
* Row (zero-based) in the test spreadsheet where the function examples start.
*/
- public static final int START_FUNCTIONS_ROW_INDEX = 95; // Row '96'
+ int START_FUNCTIONS_ROW_INDEX = 95; // Row '96'
/**
* Index of the column that contains the function names
*/
- public static final int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'
+ int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'
/**
* Used to indicate when there are no more functions left
*/
- public static final String FUNCTION_NAMES_END_SENTINEL = "";
+ String FUNCTION_NAMES_END_SENTINEL = "";
/**
* Index of the column where the test values start (for each function)
*/
- public static final short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'
+ short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'
/**
* Each function takes 4 rows in the test spreadsheet
*/
- public static final int NUMBER_OF_ROWS_PER_FUNCTION = 4;
+ int NUMBER_OF_ROWS_PER_FUNCTION = 4;
}
- private XSSFWorkbook workbook;
- private Sheet sheet;
- // Note - multiple failures are aggregated before ending.
- // If one or more functions fail, a single AssertionFailedError is thrown at the end
- private int _functionFailureCount;
- private int _functionSuccessCount;
- private int _evaluationFailureCount;
- private int _evaluationSuccessCount;
+ @Parameter(value = 0)
+ public String targetFunctionName;
+ @Parameter(value = 1)
+ public int formulasRowIdx;
+ @Parameter(value = 2)
+ public int expectedValuesRowIdx;
- private static final Cell getExpectedValueCell(Row row, short columnIndex) {
- if (row == null) {
- return null;
- }
- return row.getCell(columnIndex);
- }
+ @AfterClass
+ public static void closeResource() throws Exception {
+ LocaleUtil.setUserLocale(userLocale);
+ workbook.close();
+ }
+
+ @Parameters(name="{0}")
+ public static Collection