aboutsummaryrefslogtreecommitdiffstats
path: root/poi/src
diff options
context:
space:
mode:
Diffstat (limited to 'poi/src')
-rw-r--r--poi/src/main/java/org/apache/poi/hssf/record/TextObjectRecord.java2
-rw-r--r--poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java3
-rw-r--r--poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFName.java2
-rw-r--r--poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFSheet.java2
-rw-r--r--poi/src/main/java/org/apache/poi/hssf/usermodel/HeaderFooter.java2
-rw-r--r--poi/src/main/java/org/apache/poi/hssf/usermodel/helpers/HSSFRowColShifter.java16
-rw-r--r--poi/src/main/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java17
-rw-r--r--poi/src/main/java/org/apache/poi/poifs/filesystem/DocumentDescriptor.java2
-rw-r--r--poi/src/main/java/org/apache/poi/poifs/property/PropertyTable.java13
-rw-r--r--poi/src/main/java/org/apache/poi/ss/format/CellFormatPart.java6
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/EvaluationConditionalFormatRule.java2
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java2
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/atp/TextJoinFunction.java2
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/function/FunctionMetadataReader.java4
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/functions/BaseNumberUtils.java2
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/functions/Code.java2
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/functions/Complex.java2
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/functions/Countif.java2
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/functions/Imaginary.java2
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/functions/Rept.java3
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/functions/Value.java2
-rw-r--r--poi/src/main/java/org/apache/poi/ss/usermodel/DateUtil.java43
-rw-r--r--poi/src/main/java/org/apache/poi/ss/util/AreaReference.java4
-rw-r--r--poi/src/main/java/org/apache/poi/ss/util/CellReference.java8
-rw-r--r--poi/src/main/java/org/apache/poi/ss/util/CellUtil.java16
-rw-r--r--poi/src/main/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java22
-rw-r--r--poi/src/main/java/org/apache/poi/util/TempFile.java64
-rw-r--r--poi/src/test/java/org/apache/poi/POIDataSamples.java2
-rw-r--r--poi/src/test/java/org/apache/poi/hssf/eventusermodel/TestFormatTrackingHSSFListener.java4
-rw-r--r--poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java26
-rw-r--r--poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFRowCopyRowFrom.java130
-rw-r--r--poi/src/test/java/org/apache/poi/ss/formula/function/ExcelCetabFunctionExtractor.java2
-rw-r--r--poi/src/test/java/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java2
-rw-r--r--poi/src/test/java/org/apache/poi/ss/util/TestCellUtil.java36
-rw-r--r--poi/src/test/java/org/apache/poi/util/DefaultTempFileCreationStrategyTest.java106
-rw-r--r--poi/src/test/java/org/apache/poi/util/TestThreadLocalTempFile.java68
36 files changed, 527 insertions, 96 deletions
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/TextObjectRecord.java b/poi/src/main/java/org/apache/poi/hssf/record/TextObjectRecord.java
index 17bcce71e7..d4a303f873 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/TextObjectRecord.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/TextObjectRecord.java
@@ -212,7 +212,7 @@ public final class TextObjectRecord extends ContinuableRecord {
protected void serialize(ContinuableRecordOutput out) {
serializeTXORecord(out);
- if (_text.getString().length() > 0) {
+ if (!_text.getString().isEmpty()) {
serializeTrailingRecords(out);
}
}
diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
index d1fe755fc3..20d3bcaf6e 100644
--- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
+++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
@@ -858,10 +858,11 @@ public final class HSSFCellStyle implements CellStyle, Duplicatable {
public void cloneStyleFrom(CellStyle source) {
if(source instanceof HSSFCellStyle) {
this.cloneStyleFrom((HSSFCellStyle)source);
- } else if (_hssfWorkbook != null) {
+ } else {
CellUtil.cloneStyle(source, this, _hssfWorkbook);
}
}
+
public void cloneStyleFrom(HSSFCellStyle source) {
// First we need to clone the extended format
// record
diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFName.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFName.java
index 75d8c0a303..60fdffa599 100644
--- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFName.java
+++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFName.java
@@ -180,7 +180,7 @@ public final class HSSFName implements Name {
*/
private static void validateName(String name) {
- if (name.length() == 0) {
+ if (name.isEmpty()) {
throw new IllegalArgumentException("Name cannot be blank");
}
if (name.length() > 255) {
diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
index bba313f57d..9e56f37714 100644
--- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
+++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
@@ -645,7 +645,7 @@ public final class HSSFSheet implements Sheet {
}
ExtendedFormatRecord xf = _book.getExFormatAt(styleIndex);
- return new HSSFCellStyle(styleIndex, xf, _book);
+ return new HSSFCellStyle(styleIndex, xf, _workbook);
}
/**
diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HeaderFooter.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HeaderFooter.java
index aa883dd44e..3884462587 100644
--- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HeaderFooter.java
+++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HeaderFooter.java
@@ -282,7 +282,7 @@ public abstract class HeaderFooter implements org.apache.poi.ss.usermodel.Header
int pos;
// Check we really got something to work on
- if (pText == null || pText.length() == 0) {
+ if (pText == null || pText.isEmpty()) {
return pText;
}
diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/helpers/HSSFRowColShifter.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/helpers/HSSFRowColShifter.java
index 698f1d7279..dc68c77dcb 100644
--- a/poi/src/main/java/org/apache/poi/hssf/usermodel/helpers/HSSFRowColShifter.java
+++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/helpers/HSSFRowColShifter.java
@@ -62,19 +62,19 @@ import static org.apache.logging.log4j.util.Unbox.box;
}
/**
- * Update the formulas in specified row using the formula shifting policy specified by shifter
+ * Update the formulas in the specified row using the formula shifting policy specified by shifter
*
* @param row the row to update the formulas on
* @param formulaShifter the formula shifting policy
*/
/*package*/ static void updateRowFormulas(HSSFRow row, FormulaShifter formulaShifter) {
- HSSFSheet sheet = row.getSheet();
- for (Cell c : row) {
- HSSFCell cell = (HSSFCell) c;
- String formula = cell.getCellFormula();
- if (formula.length() > 0) {
- String shiftedFormula = shiftFormula(row, formula, formulaShifter);
- cell.setCellFormula(shiftedFormula);
+ for (Cell cell : row) {
+ if (cell.getCellType() == CellType.FORMULA) {
+ String formula = cell.getCellFormula();
+ if (formula != null && !formula.isEmpty()) {
+ String shiftedFormula = shiftFormula(row, formula, formulaShifter);
+ cell.setCellFormula(shiftedFormula);
+ }
}
}
}
diff --git a/poi/src/main/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java b/poi/src/main/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java
index b8d443aab4..4cb3ebb4e2 100644
--- a/poi/src/main/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java
+++ b/poi/src/main/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java
@@ -141,22 +141,23 @@ public class POIFSReader
* assumed
* @param name the document name
*
- * @throws NullPointerException if listener is null or name is
- * null or empty
+ * @throws NullPointerException if listener is null or name is null
* @throws IllegalStateException if read() has already been
- * called
+ * called or name is empty
*/
-
public void registerListener(final POIFSReaderListener listener,
final POIFSDocumentPath path,
final String name) {
- if ((listener == null) || (name == null) || (name.length() == 0)) {
- throw new NullPointerException();
+ if (listener == null || name == null) {
+ throw new NullPointerException("invalid null parameter");
+ }
+ if (name.isEmpty()) {
+ throw new IllegalStateException("name must not be empty");
}
if (registryClosed) {
- throw new IllegalStateException();
+ throw new IllegalStateException("registry closed");
}
- registry.registerListener(listener, (path == null) ? new POIFSDocumentPath() : path, name);
+ registry.registerListener(listener, path == null ? new POIFSDocumentPath() : path, name);
}
/**
diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/DocumentDescriptor.java b/poi/src/main/java/org/apache/poi/poifs/filesystem/DocumentDescriptor.java
index b8d783638e..40ffdffaec 100644
--- a/poi/src/main/java/org/apache/poi/poifs/filesystem/DocumentDescriptor.java
+++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/DocumentDescriptor.java
@@ -46,7 +46,7 @@ public class DocumentDescriptor
{
throw new NullPointerException("name must not be null");
}
- if (name.length() == 0)
+ if (name.isEmpty())
{
throw new IllegalArgumentException("name cannot be empty");
}
diff --git a/poi/src/main/java/org/apache/poi/poifs/property/PropertyTable.java b/poi/src/main/java/org/apache/poi/poifs/property/PropertyTable.java
index 203f23cd46..062627ae52 100644
--- a/poi/src/main/java/org/apache/poi/poifs/property/PropertyTable.java
+++ b/poi/src/main/java/org/apache/poi/poifs/property/PropertyTable.java
@@ -83,11 +83,14 @@ public final class PropertyTable implements BATManaged {
for (ByteBuffer bb : dataSource) {
// Turn it into an array
- byte[] data;
- if (bb.hasArray() && bb.arrayOffset() == 0 &&
- bb.array().length == _bigBigBlockSize.getBigBlockSize()) {
- data = bb.array();
- } else {
+ byte[] data = null;
+ if (bb.hasArray() && bb.arrayOffset() == 0) {
+ final byte[] array = bb.array();
+ if (array.length == _bigBigBlockSize.getBigBlockSize()) {
+ data = array;
+ }
+ }
+ if (data == null) {
data = IOUtils.safelyAllocate(_bigBigBlockSize.getBigBlockSize(), POIFSFileSystem.getMaxRecordLength());
int toRead = data.length;
diff --git a/poi/src/main/java/org/apache/poi/ss/format/CellFormatPart.java b/poi/src/main/java/org/apache/poi/ss/format/CellFormatPart.java
index 990181baad..ea8eaa37b4 100644
--- a/poi/src/main/java/org/apache/poi/ss/format/CellFormatPart.java
+++ b/poi/src/main/java/org/apache/poi/ss/format/CellFormatPart.java
@@ -251,7 +251,7 @@ public class CellFormatPart {
*/
private static Color getColor(Matcher m) {
String cdesc = m.group(COLOR_GROUP);
- if (cdesc == null || cdesc.length() == 0)
+ if (cdesc == null || cdesc.isEmpty())
return null;
Color c = NAMED_COLORS.get(cdesc);
if (c == null) {
@@ -270,7 +270,7 @@ public class CellFormatPart {
*/
private CellFormatCondition getCondition(Matcher m) {
String mdesc = m.group(CONDITION_OPERATOR_GROUP);
- if (mdesc == null || mdesc.length() == 0)
+ if (mdesc == null || mdesc.isEmpty())
return null;
return CellFormatCondition.getInstance(m.group(
CONDITION_OPERATOR_GROUP), m.group(CONDITION_VALUE_GROUP));
@@ -509,7 +509,7 @@ public class CellFormatPart {
StringBuffer fmt = new StringBuffer();
while (m.find()) {
String part = group(m, 0);
- if (part.length() > 0) {
+ if (!part.isEmpty()) {
String repl = partHandler.handlePart(m, part, type, fmt);
if (repl == null) {
switch (part.charAt(0)) {
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/EvaluationConditionalFormatRule.java b/poi/src/main/java/org/apache/poi/ss/formula/EvaluationConditionalFormatRule.java
index 54199cbfca..3d0e441dbc 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/EvaluationConditionalFormatRule.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/EvaluationConditionalFormatRule.java
@@ -357,7 +357,7 @@ public class EvaluationConditionalFormatRule implements Comparable<EvaluationCon
String f2 = rule.getFormula2();
ValueEval eval2 = BlankEval.instance;
- if (f2 != null && f2.length() > 0) {
+ if (f2 != null && !f2.isEmpty()) {
eval2 = unwrapEval(workbookEvaluator.evaluate(f2, ConditionalFormattingEvaluator.getRef(cell), region));
}
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java b/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java
index 020ae38d8c..c748231838 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java
@@ -483,7 +483,7 @@ public final class FormulaParser {
} else {
// Is it a named range?
String name = parseAsName();
- if (name.length() == 0) {
+ if (name.isEmpty()) {
throw new FormulaParseException("Cell reference or Named Range "
+ "expected after sheet name at index " + _pointer + ".");
}
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/atp/TextJoinFunction.java b/poi/src/main/java/org/apache/poi/ss/formula/atp/TextJoinFunction.java
index 5e7ffe8b87..45b3ec31ac 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/atp/TextJoinFunction.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/atp/TextJoinFunction.java
@@ -86,7 +86,7 @@ final class TextJoinFunction implements FreeRefFunction {
String textValue = OperandResolver.coerceValueToString(textArg);
// If we're not ignoring empty values or if our value is not empty, add it to the list
- if (!ignoreEmpty || (textValue != null && textValue.length() > 0)) {
+ if (!ignoreEmpty || (textValue != null && !textValue.isEmpty())) {
textValues.add(textValue);
}
}
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/function/FunctionMetadataReader.java b/poi/src/main/java/org/apache/poi/ss/formula/function/FunctionMetadataReader.java
index 349e62f044..4b6e6fa2e7 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/function/FunctionMetadataReader.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/function/FunctionMetadataReader.java
@@ -124,7 +124,7 @@ final class FunctionMetadataReader {
byte returnClassCode = parseReturnTypeCode(parts[4]);
byte[] parameterClassCodes = parseOperandTypeCodes(parts[5]);
// 6 isVolatile
- boolean hasNote = parts[7].length() > 0;
+ boolean hasNote = !parts[7].isEmpty();
validateFunctionName(functionName);
// TODO - make POI use isVolatile
@@ -134,7 +134,7 @@ final class FunctionMetadataReader {
private static byte parseReturnTypeCode(String code) {
- if(code.length() == 0) {
+ if(code.isEmpty()) {
return Ptg.CLASS_REF; // happens for GETPIVOTDATA
}
return parseOperandTypeCode(code);
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/BaseNumberUtils.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/BaseNumberUtils.java
index c39d082e10..db583f3229 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/functions/BaseNumberUtils.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/BaseNumberUtils.java
@@ -23,7 +23,7 @@ public class BaseNumberUtils {
public static double convertToDecimal(String value, int base, int maxNumberOfPlaces) throws IllegalArgumentException {
- if (value == null || value.length() == 0) {
+ if (value == null || value.isEmpty()) {
return 0.0;
}
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Code.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Code.java
index 96f2a13204..30f2d3257f 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Code.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Code.java
@@ -41,7 +41,7 @@ public class Code extends Fixed1ArgFunction {
}
String text = OperandResolver.coerceValueToString(veText1);
- if (text.length() == 0) {
+ if (text.isEmpty()) {
return ErrorEval.VALUE_INVALID;
}
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Complex.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Complex.java
index a10c54a758..a4fac2685e 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Complex.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Complex.java
@@ -90,7 +90,7 @@ public class Complex extends Var2or3ArgFunction implements FreeRefFunction {
}
String suffixValue = OperandResolver.coerceValueToString(suffix);
- if (suffixValue.length() == 0) {
+ if (suffixValue.isEmpty()) {
suffixValue = DEFAULT_SUFFIX;
}
if (suffixValue.equals(DEFAULT_SUFFIX.toUpperCase(Locale.ROOT)) ||
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Countif.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Countif.java
index 93fdf033a4..ecb57e5e1a 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Countif.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Countif.java
@@ -339,7 +339,7 @@ public final class Countif extends Fixed2ArgFunction {
switch(getCode()) {
case CmpOp.NONE:
case CmpOp.EQ:
- return _value.length() == 0;
+ return _value.isEmpty();
case CmpOp.NE:
// pred '<>' matches empty string but not blank cell
// pred '<>ABC' matches blank and 'not ABC'
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Imaginary.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Imaginary.java
index 012aacdd01..f478c95d5b 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Imaginary.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Imaginary.java
@@ -74,7 +74,7 @@ public class Imaginary extends Fixed1ArgFunction implements FreeRefFunction {
String imaginaryGroup = m.group(5);
boolean hasImaginaryPart = imaginaryGroup.equals("i") || imaginaryGroup.equals("j");
- if (imaginaryGroup.length() == 0) {
+ if (imaginaryGroup.isEmpty()) {
return new StringEval(String.valueOf(0));
}
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Rept.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Rept.java
index c3be177ce3..33b2c46366 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Rept.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Rept.java
@@ -40,7 +40,6 @@ import org.apache.poi.ss.formula.eval.ValueEval;
*/
public class Rept extends Fixed2ArgFunction {
-
@Override
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval text, ValueEval number_times) {
@@ -64,7 +63,7 @@ public class Rept extends Fixed2ArgFunction {
strb.append(strText1);
}
- if (strb.toString().length() > 32767) {
+ if (strb.length() > 32767) {
return ErrorEval.VALUE_INVALID;
}
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Value.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Value.java
index 451f0a2fab..87edae4b0e 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Value.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Value.java
@@ -152,7 +152,7 @@ public final class Value extends Fixed1ArgFunction implements ArrayFunction {
foundPercentage = true;
break;
}
- if (remainingTextTrimmed.length() > 0) {
+ if (!remainingTextTrimmed.isEmpty()) {
// intervening spaces not allowed once the digits start
return null;
}
diff --git a/poi/src/main/java/org/apache/poi/ss/usermodel/DateUtil.java b/poi/src/main/java/org/apache/poi/ss/usermodel/DateUtil.java
index 8018267a26..401b1c47a1 100644
--- a/poi/src/main/java/org/apache/poi/ss/usermodel/DateUtil.java
+++ b/poi/src/main/java/org/apache/poi/ss/usermodel/DateUtil.java
@@ -70,7 +70,7 @@ public class DateUtil {
private static final Pattern date_ptrn2 = Pattern.compile("^\\[[a-zA-Z]+]");
private static final Pattern date_ptrn3a = Pattern.compile("[yYmMdDhHsS]");
// add "\u5e74 \u6708 \u65e5" for Chinese/Japanese date format:2017 \u5e74 2 \u6708 7 \u65e5
- private static final Pattern date_ptrn3b = Pattern.compile("^[\\[\\]yYmMdDhHsS\\-T/\u5e74\u6708\u65e5,. :\"\\\\]+0*[ampAMP/]*$");
+ private static final Pattern date_ptrn3b = Pattern.compile("^[\\[\\]yYmMdDhHsS\\-T/\u5e74\u6708\u65e5,. :\"\\\\]+0* ?[ampAMP/]*$");
// elapsed time patterns: [h],[m] and [s]
private static final Pattern date_ptrn4 = Pattern.compile("^\\[([hH]+|[mM]+|[sS]+)]");
@@ -548,6 +548,7 @@ public class DateUtil {
// avoid re-checking DateUtil.isADateFormat(int, String) if a given format
// string represents a date format if the same string is passed multiple times.
// see https://issues.apache.org/bugzilla/show_bug.cgi?id=55611
+ private static boolean maintainCache = true;
private static final ThreadLocal<Integer> lastFormatIndex = ThreadLocal.withInitial(() -> -1);
private static final ThreadLocal<String> lastFormatString = new ThreadLocal<>();
private static final ThreadLocal<Boolean> lastCachedResult = new ThreadLocal<>();
@@ -561,22 +562,24 @@ public class DateUtil {
}
private static boolean isCached(String formatString, int formatIndex) {
- return formatIndex == lastFormatIndex.get()
+ return maintainCache && formatIndex == lastFormatIndex.get()
&& formatString.equals(lastFormatString.get());
}
private static void cache(String formatString, int formatIndex, boolean cached) {
- if (formatString == null || "".equals(formatString)) {
- lastFormatString.remove();
- } else {
- lastFormatString.set(formatString);
- }
- if (formatIndex == -1) {
- lastFormatIndex.remove();
- } else {
- lastFormatIndex.set(formatIndex);
+ if (maintainCache) {
+ if (formatString == null || "".equals(formatString)) {
+ lastFormatString.remove();
+ } else {
+ lastFormatString.set(formatString);
+ }
+ if (formatIndex == -1) {
+ lastFormatIndex.remove();
+ } else {
+ lastFormatIndex.set(formatIndex);
+ }
+ lastCachedResult.set(cached);
}
- lastCachedResult.set(cached);
}
/**
@@ -624,7 +627,7 @@ public class DateUtil {
}
// If we didn't get a real string, don't even cache it as we can always find this out quickly
- if(formatString == null || formatString.length() == 0) {
+ if(formatString == null || formatString.isEmpty()) {
return false;
}
@@ -997,4 +1000,18 @@ public class DateUtil {
return tm;
}
+
+ /**
+ * Enable or disable the thread-local cache for date format checking.
+ * If enabled, the date format checking will be cached per thread,
+ * which can improve performance when checking the same format multiple times.
+ * If disabled, the cache will not be used and each check will be performed independently.
+ *
+ * @param enable true to enable the cache, false to disable it (enabled, by default)
+ * @since POI 5.4.2
+ */
+ public static void enableThreadLocalCache(final boolean enable) {
+ // enable thread-local cache for date format checking
+ maintainCache = enable;
+ }
}
diff --git a/poi/src/main/java/org/apache/poi/ss/util/AreaReference.java b/poi/src/main/java/org/apache/poi/ss/util/AreaReference.java
index fc45d81b4a..fd1cb4ff51 100644
--- a/poi/src/main/java/org/apache/poi/ss/util/AreaReference.java
+++ b/poi/src/main/java/org/apache/poi/ss/util/AreaReference.java
@@ -326,7 +326,7 @@ public class AreaReference {
String currentSegment = "";
StringTokenizer st = new StringTokenizer(reference, ",");
while(st.hasMoreTokens()) {
- if (currentSegment.length() > 0) {
+ if (!currentSegment.isEmpty()) {
currentSegment += ",";
}
currentSegment += st.nextToken();
@@ -336,7 +336,7 @@ public class AreaReference {
currentSegment = "";
}
}
- if (currentSegment.length() > 0) {
+ if (!currentSegment.isEmpty()) {
results.add(currentSegment);
}
return results.toArray(new String[0]);
diff --git a/poi/src/main/java/org/apache/poi/ss/util/CellReference.java b/poi/src/main/java/org/apache/poi/ss/util/CellReference.java
index 91a97b7edf..da1202c283 100644
--- a/poi/src/main/java/org/apache/poi/ss/util/CellReference.java
+++ b/poi/src/main/java/org/apache/poi/ss/util/CellReference.java
@@ -116,22 +116,22 @@ public class CellReference implements GenericRecord {
_sheetName = parts.sheetName;
String colRef = parts.colRef;
- _isColAbs = (colRef.length() > 0) && colRef.charAt(0) == '$';
+ _isColAbs = (!colRef.isEmpty()) && colRef.charAt(0) == '$';
if (_isColAbs) {
colRef = colRef.substring(1);
}
- if (colRef.length() == 0) {
+ if (colRef.isEmpty()) {
_colIndex = -1;
} else {
_colIndex = convertColStringToIndex(colRef);
}
String rowRef=parts.rowRef;
- _isRowAbs = (rowRef.length() > 0) && rowRef.charAt(0) == '$';
+ _isRowAbs = (!rowRef.isEmpty()) && rowRef.charAt(0) == '$';
if (_isRowAbs) {
rowRef = rowRef.substring(1);
}
- if (rowRef.length() == 0) {
+ if (rowRef.isEmpty()) {
_rowIndex = -1;
} else {
// throws NumberFormatException if rowRef is not convertible to an int
diff --git a/poi/src/main/java/org/apache/poi/ss/util/CellUtil.java b/poi/src/main/java/org/apache/poi/ss/util/CellUtil.java
index d0ee0db55b..b2879fb7fd 100644
--- a/poi/src/main/java/org/apache/poi/ss/util/CellUtil.java
+++ b/poi/src/main/java/org/apache/poi/ss/util/CellUtil.java
@@ -280,6 +280,7 @@ public final class CellUtil {
map.put(LEFT_BORDER_COLOR, CellPropertyType.LEFT_BORDER_COLOR);
map.put(RIGHT_BORDER_COLOR, CellPropertyType.RIGHT_BORDER_COLOR);
map.put(TOP_BORDER_COLOR, CellPropertyType.TOP_BORDER_COLOR);
+ map.put(DATA_FORMAT, CellPropertyType.DATA_FORMAT);
map.put(FILL_BACKGROUND_COLOR, CellPropertyType.FILL_BACKGROUND_COLOR);
map.put(FILL_FOREGROUND_COLOR, CellPropertyType.FILL_FOREGROUND_COLOR);
map.put(FILL_BACKGROUND_COLOR_COLOR, CellPropertyType.FILL_BACKGROUND_COLOR_COLOR);
@@ -289,10 +290,11 @@ public final class CellUtil {
map.put(HIDDEN, CellPropertyType.HIDDEN);
map.put(INDENTION, CellPropertyType.INDENTION);
map.put(LOCKED, CellPropertyType.LOCKED);
+ map.put(QUOTE_PREFIXED, CellPropertyType.QUOTE_PREFIXED);
map.put(ROTATION, CellPropertyType.ROTATION);
- map.put(VERTICAL_ALIGNMENT, CellPropertyType.VERTICAL_ALIGNMENT);
map.put(SHRINK_TO_FIT, CellPropertyType.SHRINK_TO_FIT);
- map.put(QUOTE_PREFIXED, CellPropertyType.QUOTE_PREFIXED);
+ map.put(VERTICAL_ALIGNMENT, CellPropertyType.VERTICAL_ALIGNMENT);
+ map.put(WRAP_TEXT, CellPropertyType.WRAP_TEXT);
namePropertyMap = Collections.unmodifiableMap(map);
}
@@ -572,7 +574,7 @@ public final class CellUtil {
@Deprecated
@Removal(version = "7.0.0")
public static void setCellStyleProperties(Cell cell, Map<String, Object> properties) {
- EnumMap<CellPropertyType, Object> strPropMap = new EnumMap<>(CellPropertyType.class);
+ final EnumMap<CellPropertyType, Object> strPropMap = new EnumMap<>(CellPropertyType.class);
properties.forEach((k, v) -> strPropMap.put(namePropertyMap.get(k), v));
setCellStyleProperties(cell, strPropMap, false);
}
@@ -685,10 +687,16 @@ public final class CellUtil {
* @param cell The cell that is to be changed.
* @param property The name of the property that is to be changed.
* @param propertyValue The value of the property that is to be changed.
- *
+ * @throws NullPointerException if {@code cell} or {@code property} is null
* @since POI 5.4.0
*/
public static void setCellStyleProperty(Cell cell, CellPropertyType property, Object propertyValue) {
+ if (cell == null) {
+ throw new NullPointerException("Cell must not be null");
+ }
+ if (property == null) {
+ throw new NullPointerException("CellPropertyType must not be null");
+ }
boolean disableNullColorCheck = false;
final Map<CellPropertyType, Object> propMap;
if (CellPropertyType.FILL_FOREGROUND_COLOR_COLOR.equals(property) && propertyValue == null) {
diff --git a/poi/src/main/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java b/poi/src/main/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java
index 9b2e711ed4..584f7dec4c 100644
--- a/poi/src/main/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java
+++ b/poi/src/main/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java
@@ -52,6 +52,9 @@ public class DefaultTempFileCreationStrategy implements TempFileCreationStrategy
/** The directory where the temporary files will be created (<code>null</code> to use the default directory). */
private volatile File dir;
+ /** The directory where that was passed to the constructor (<code>null</code> to use the default directory). */
+ private final File initDir;
+
/** The lock to make dir initialized only once. */
private final Lock dirLock = new ReentrantLock();
@@ -65,14 +68,23 @@ public class DefaultTempFileCreationStrategy implements TempFileCreationStrategy
}
/**
- * Creates the strategy allowing to set the
+ * Creates the strategy allowing to set a custom directory for the temporary files.
+ * <p>
+ * If you provide a non-null dir as input, it must be a directory (if it already exists).
+ * Since POI 5.4.2, this is checked at construction time. In previous versions, it was checked
+ * at the first call to {@link #createTempFile(String, String)} or {@link #createTempDirectory(String)}.
+ * </p>
*
* @param dir The directory where the temporary files will be created (<code>null</code> to use the default directory).
- *
+ * @throws IllegalArgumentException if the provided directory does not exist or is not a directory
* @see Files#createTempFile(Path, String, String, FileAttribute[])
*/
public DefaultTempFileCreationStrategy(File dir) {
+ this.initDir = dir;
this.dir = dir;
+ if (dir != null && dir.exists() && !dir.isDirectory()) {
+ throw new IllegalArgumentException("The provided file is not a directory: " + dir);
+ }
}
@Override
@@ -117,7 +129,11 @@ public class DefaultTempFileCreationStrategy implements TempFileCreationStrategy
}
protected Path getPOIFilesDirectoryPath() throws IOException {
- return Paths.get(getJavaIoTmpDir(), POIFILES);
+ if (initDir == null) {
+ return Paths.get(getJavaIoTmpDir(), POIFILES);
+ } else {
+ return initDir.toPath();
+ }
}
// Create our temp dir only once by double-checked locking
diff --git a/poi/src/main/java/org/apache/poi/util/TempFile.java b/poi/src/main/java/org/apache/poi/util/TempFile.java
index 46bf8ccc8b..2b668dc885 100644
--- a/poi/src/main/java/org/apache/poi/util/TempFile.java
+++ b/poi/src/main/java/org/apache/poi/util/TempFile.java
@@ -19,6 +19,8 @@ package org.apache.poi.util;
import java.io.File;
import java.io.IOException;
+import java.util.Objects;
+import java.util.function.Supplier;
/**
* Interface for creating temporary files. Collects them all into one directory by default.
@@ -27,7 +29,14 @@ public final class TempFile {
/** The strategy used by {@link #createTempFile(String, String)} to create the temporary files. */
private static TempFileCreationStrategy strategy = new DefaultTempFileCreationStrategy();
- /** Define a constant for this property as it is sometimes mistypes as "tempdir" otherwise */
+ /** If set for the thread, this is used instead of the strategy variable above. */
+ private static final ThreadLocal<TempFileCreationStrategy> threadLocalStrategy = new ThreadLocal<>();
+ static {
+ // allow to clear all thread-locals via ThreadLocalUtil
+ ThreadLocalUtil.registerCleaner(threadLocalStrategy::remove);
+ }
+
+ /** Define a constant for this property as it is sometimes mistyped as "tempdir" otherwise */
public static final String JAVA_IO_TMPDIR = "java.io.tmpdir";
private TempFile() {
@@ -47,6 +56,21 @@ public final class TempFile {
}
TempFile.strategy = strategy;
}
+
+ /**
+ * Configures the strategy used by {@link #createTempFile(String, String)} to create the temporary files.
+ *
+ * @param strategy The new strategy to be used to create the temporary files for this thread.
+ * <code>null</code> can be used to reset the strategy for this thread to the default one.
+ * @since POI 5.4.2
+ */
+ public static void setThreadLocalTempFileCreationStrategy(TempFileCreationStrategy strategy) {
+ if (strategy == null) {
+ threadLocalStrategy.remove();
+ } else {
+ threadLocalStrategy.set(strategy);
+ }
+ }
/**
* Creates a new and empty temporary file. By default, files are collected into one directory and are not
@@ -64,10 +88,44 @@ public final class TempFile {
* @throws IOException If no temporary file could be created.
*/
public static File createTempFile(String prefix, String suffix) throws IOException {
- return strategy.createTempFile(prefix, suffix);
+ return getStrategy().createTempFile(prefix, suffix);
}
public static File createTempDirectory(String name) throws IOException {
- return strategy.createTempDirectory(name);
+ return getStrategy().createTempDirectory(name);
+ }
+
+ /**
+ * Executes the given task ensuring that POI will use the given temp file creation strategy
+ * within the scope of the given task. The change of strategy is not visible to other threads,
+ * and the previous strategy is restored after the task completed (normally or exceptionally).
+ *
+ * @param newStrategy the temp file strategy to be used in the scope of the given task
+ * @param task the task to be executed with the given temp file strategy
+ * @return the result of the given task
+ *
+ * @since POI 5.4.2
+ */
+ public static <R> R withStrategy(TempFileCreationStrategy newStrategy, Supplier<? extends R> task) {
+ Objects.requireNonNull(newStrategy, "newStrategy");
+ Objects.requireNonNull(task, "task");
+
+ TempFileCreationStrategy oldStrategy = threadLocalStrategy.get();
+ try {
+ threadLocalStrategy.set(newStrategy);
+ return task.get();
+ } finally {
+ setThreadLocalTempFileCreationStrategy(oldStrategy);
+ }
+ }
+
+ private static TempFileCreationStrategy getStrategy() {
+ final TempFileCreationStrategy s = threadLocalStrategy.get();
+ if (s == null) {
+ threadLocalStrategy.remove();
+ return strategy;
+ } else {
+ return s;
+ }
}
}
diff --git a/poi/src/test/java/org/apache/poi/POIDataSamples.java b/poi/src/test/java/org/apache/poi/POIDataSamples.java
index e15843f377..f976cd0c91 100644
--- a/poi/src/test/java/org/apache/poi/POIDataSamples.java
+++ b/poi/src/test/java/org/apache/poi/POIDataSamples.java
@@ -169,7 +169,7 @@ public final class POIDataSamples {
+ "' not found in data dir '" + _resolvedDataDir.getAbsolutePath() + "'");
}
try {
- if(sampleFileName.length() > 0) {
+ if(!sampleFileName.isEmpty()) {
String fn = sampleFileName;
if(fn.indexOf('/') > 0) {
fn = fn.substring(fn.indexOf('/')+1);
diff --git a/poi/src/test/java/org/apache/poi/hssf/eventusermodel/TestFormatTrackingHSSFListener.java b/poi/src/test/java/org/apache/poi/hssf/eventusermodel/TestFormatTrackingHSSFListener.java
index 2a99b3b395..3ef75d7f3d 100644
--- a/poi/src/test/java/org/apache/poi/hssf/eventusermodel/TestFormatTrackingHSSFListener.java
+++ b/poi/src/test/java/org/apache/poi/hssf/eventusermodel/TestFormatTrackingHSSFListener.java
@@ -16,7 +16,9 @@
==================================================================== */
package org.apache.poi.hssf.eventusermodel;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -96,7 +98,7 @@ final class TestFormatTrackingHSSFListener {
// Should always give us a string
String s = listener.formatNumberDateCell(cvr);
assertNotNull(s);
- assertTrue(s.length() > 0);
+ assertNotEquals(0, s.length());
}
}
diff --git a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java
index 2949dbeeee..61cd1aba69 100644
--- a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java
+++ b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java
@@ -27,6 +27,7 @@ import java.util.TimeZone;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.InternalWorkbook;
+import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
import org.junit.jupiter.api.AfterAll;
@@ -60,7 +61,7 @@ class TestHSSFDateUtil {
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("DateFormats.xls");
HSSFSheet sheet = workbook.getSheetAt(0);
- InternalWorkbook wb = workbook.getWorkbook();
+ InternalWorkbook wb = workbook.getWorkbook();
assertNotNull(wb);
HSSFRow row;
@@ -115,4 +116,27 @@ class TestHSSFDateUtil {
workbook.close();
}
+
+ @Test
+ void testIsADateFormat() throws IOException {
+ try (HSSFWorkbook workbook = new HSSFWorkbook()) {
+ HSSFSheet sheet = workbook.createSheet();
+ HSSFRow row = sheet.createRow(0);
+ HSSFCell cell = row.createCell(0);
+ cell.setCellValue(45825.5); // 2025-06-17 (midday)
+ HSSFCellStyle style = workbook.createCellStyle();
+ style.setDataFormat(workbook.createDataFormat().getFormat("DD MMMM, YYYY hh:mm:ss.000 AM/PM"));
+ cell.setCellStyle(style);
+ DateUtil.enableThreadLocalCache(false);
+ try {
+ assertTrue(DateUtil.isCellDateFormatted(cell), "cell is date formatted?");
+ DataFormatter formatter = new DataFormatter();
+ String formattedValue = formatter.formatCellValue(cell);
+ assertEquals("17 June, 2025 12:00:00.000 PM", formattedValue);
+ } finally {
+ DateUtil.enableThreadLocalCache(true);
+ }
+ }
+ }
+
}
diff --git a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFRowCopyRowFrom.java b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFRowCopyRowFrom.java
new file mode 100644
index 0000000000..67dcc38f46
--- /dev/null
+++ b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFRowCopyRowFrom.java
@@ -0,0 +1,130 @@
+/* ====================================================================
+ 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.hssf.usermodel;
+
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellCopyContext;
+import org.apache.poi.ss.usermodel.CellCopyPolicy;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Iterator;
+
+public class TestHSSFRowCopyRowFrom {
+ @Test
+ void testCopyFrom() throws IOException {
+ CellCopyPolicy cellCopyPolicy = new CellCopyPolicy.Builder()
+ .cellFormula(false) // NOTE: setting to false allows for copying the evaluated formula value.
+ .cellStyle(CellCopyPolicy.DEFAULT_COPY_CELL_STYLE_POLICY)
+ .cellValue(CellCopyPolicy.DEFAULT_COPY_CELL_VALUE_POLICY)
+ .condenseRows(CellCopyPolicy.DEFAULT_CONDENSE_ROWS_POLICY)
+ .copyHyperlink(CellCopyPolicy.DEFAULT_COPY_HYPERLINK_POLICY)
+ .mergeHyperlink(CellCopyPolicy.DEFAULT_MERGE_HYPERLINK_POLICY)
+ .mergedRegions(CellCopyPolicy.DEFAULT_COPY_MERGED_REGIONS_POLICY)
+ .rowHeight(CellCopyPolicy.DEFAULT_COPY_ROW_HEIGHT_POLICY)
+ .build();
+
+ final LocalDateTime localDateTime = LocalDateTime.of(2023, 1, 1, 0, 0, 0);
+ final LocalDateTime nonValidExcelDate = LocalDateTime.of(1899, 12, 31, 0, 0, 0);
+ final Object[][] data = {
+ {"transaction_id", "transaction_date", "transaction_time"},
+ {75, localDateTime, nonValidExcelDate.plusHours(9).plusMinutes(53).plusSeconds(44).toLocalTime()},
+ {78, localDateTime, nonValidExcelDate.plusHours(9).plusMinutes(55).plusSeconds(16).toLocalTime()}
+ };
+
+ final UnsynchronizedByteArrayOutputStream workbookOutputStream =
+ UnsynchronizedByteArrayOutputStream.builder().get();
+ try (Workbook workbook = new HSSFWorkbook()) {
+ final Sheet sheet = workbook.createSheet("SomeSheetName");
+ populateSheet(sheet, data);
+ setCellStyles(sheet, workbook);
+ workbook.write(workbookOutputStream);
+ }
+
+ try (HSSFWorkbook originalWorkbook = new HSSFWorkbook(workbookOutputStream.toInputStream())) {
+ final Iterator<Sheet> originalSheetsIterator = originalWorkbook.sheetIterator();
+ final CellCopyContext cellCopyContext = new CellCopyContext();
+
+ while (originalSheetsIterator.hasNext()) {
+ final HSSFSheet originalSheet = (HSSFSheet) originalSheetsIterator.next();
+ final String originalSheetName = originalSheet.getSheetName();
+ final Iterator<Row> originalRowsIterator = originalSheet.rowIterator();
+
+ try (HSSFWorkbook newWorkbook = new HSSFWorkbook()) {
+ final HSSFSheet newSheet = newWorkbook.createSheet(originalSheetName);
+ while (originalRowsIterator.hasNext()) {
+ HSSFRow originalRow = (HSSFRow) originalRowsIterator.next();
+ HSSFRow newRow = newSheet.createRow(originalRow.getRowNum());
+ newRow.copyRowFrom(originalRow, cellCopyPolicy, cellCopyContext);
+ }
+ }
+ }
+ }
+ }
+
+ private static void populateSheet(Sheet sheet, Object[][] data) {
+ int rowCount = 0;
+ for (Object[] dataRow : data) {
+ Row row = sheet.createRow(rowCount++);
+ int columnCount = 0;
+
+ for (Object field : dataRow) {
+ Cell cell = row.createCell(columnCount++);
+ if (field instanceof String) {
+ cell.setCellValue((String) field);
+ } else if (field instanceof Integer) {
+ cell.setCellValue((Integer) field);
+ } else if (field instanceof Long) {
+ cell.setCellValue((Long) field);
+ } else if (field instanceof LocalDateTime) {
+ cell.setCellValue((LocalDateTime) field);
+ } else if (field instanceof LocalTime) {
+ cell.setCellValue(DateUtil.convertTime(DateTimeFormatter.ISO_LOCAL_TIME.format((LocalTime) field)));
+ }
+ }
+ }
+ }
+
+ void setCellStyles(Sheet sheet, Workbook workbook) {
+ CreationHelper creationHelper = workbook.getCreationHelper();
+ CellStyle dayMonthYearCellStyle = workbook.createCellStyle();
+ dayMonthYearCellStyle.setDataFormat(creationHelper.createDataFormat().getFormat("dd/mm/yyyy"));
+ CellStyle hourMinuteSecond = workbook.createCellStyle();
+ hourMinuteSecond.setDataFormat((short) 21); // 21 represents format h:mm:ss
+ for (int rowNum = sheet.getFirstRowNum() + 1; rowNum < sheet.getLastRowNum() + 1; rowNum++) {
+ Row row = sheet.getRow(rowNum);
+ row.getCell(1).setCellStyle(dayMonthYearCellStyle);
+ row.getCell(2).setCellStyle(hourMinuteSecond);
+ }
+ }
+}
diff --git a/poi/src/test/java/org/apache/poi/ss/formula/function/ExcelCetabFunctionExtractor.java b/poi/src/test/java/org/apache/poi/ss/formula/function/ExcelCetabFunctionExtractor.java
index 87c0dcd1f3..3d6f525d2b 100644
--- a/poi/src/test/java/org/apache/poi/ss/formula/function/ExcelCetabFunctionExtractor.java
+++ b/poi/src/test/java/org/apache/poi/ss/formula/function/ExcelCetabFunctionExtractor.java
@@ -149,7 +149,7 @@ public final class ExcelCetabFunctionExtractor {
public void addFunction(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams,
String returnClass, String paramClasses, String volatileFlagStr) {
- boolean isVolatile = volatileFlagStr.length() > 0;
+ boolean isVolatile = !volatileFlagStr.isEmpty();
Integer funcIxKey = Integer.valueOf(funcIx);
if(!_groupFunctionIndexes.add(funcIxKey)) {
diff --git a/poi/src/test/java/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java b/poi/src/test/java/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java
index a900169822..11dca94104 100644
--- a/poi/src/test/java/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java
+++ b/poi/src/test/java/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java
@@ -171,7 +171,7 @@ public final class ExcelFileFormatDocFunctionExtractor {
public void addFunction(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams,
String returnClass, String paramClasses, String volatileFlagStr) {
- boolean isVolatile = volatileFlagStr.length() > 0;
+ boolean isVolatile = !volatileFlagStr.isEmpty();
Integer funcIxKey = funcIx;
if(!_groupFunctionIndexes.add(funcIxKey)) {
diff --git a/poi/src/test/java/org/apache/poi/ss/util/TestCellUtil.java b/poi/src/test/java/org/apache/poi/ss/util/TestCellUtil.java
new file mode 100644
index 0000000000..b7defbef99
--- /dev/null
+++ b/poi/src/test/java/org/apache/poi/ss/util/TestCellUtil.java
@@ -0,0 +1,36 @@
+/* ====================================================================
+ 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.ss.util;
+
+import org.apache.poi.ss.usermodel.CellPropertyType;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Test for CellUtil constants
+ */
+class TestCellUtil {
+ @Test
+ void testNamePropertyMap() {
+ Arrays.stream(CellPropertyType.values()).forEach(cellPropertyType ->
+ assertTrue(CellUtil.namePropertyMap.containsValue(cellPropertyType),
+ "missing " + cellPropertyType));
+ }
+}
diff --git a/poi/src/test/java/org/apache/poi/util/DefaultTempFileCreationStrategyTest.java b/poi/src/test/java/org/apache/poi/util/DefaultTempFileCreationStrategyTest.java
index 4e4f6b779e..d60e4da8ac 100644
--- a/poi/src/test/java/org/apache/poi/util/DefaultTempFileCreationStrategyTest.java
+++ b/poi/src/test/java/org/apache/poi/util/DefaultTempFileCreationStrategyTest.java
@@ -20,11 +20,14 @@ package org.apache.poi.util;
import static org.apache.poi.util.DefaultTempFileCreationStrategy.DELETE_FILES_ON_EXIT;
import static org.apache.poi.util.DefaultTempFileCreationStrategy.POIFILES;
import static org.apache.poi.util.TempFile.JAVA_IO_TMPDIR;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.AfterEach;
@@ -59,16 +62,62 @@ class DefaultTempFileCreationStrategyTest {
checkGetFile(strategy);
}
- private static void checkGetFile(DefaultTempFileCreationStrategy strategy) throws IOException {
- File file = strategy.createTempFile("POITest", ".tmp");
+ @Test
+ void testProvidedDir() throws IOException {
+ DefaultTempFileCreationStrategy parentStrategy = new DefaultTempFileCreationStrategy();
+ File dir = parentStrategy.createTempDirectory("testProvidedDir");
+ assertNotNull(dir, "Failed to create temp directory");
try {
- assertTrue(file.getParentFile().exists(),
- "Failed for " + file.getParentFile());
+ assertTrue(Files.isDirectory(dir.toPath()), "File is not a directory: " + dir);
+ DefaultTempFileCreationStrategy testStrategy = new DefaultTempFileCreationStrategy(dir);
+ checkGetFileAndPath(testStrategy, dir.toPath());
+ } finally {
+ // Clean up the directory after the test
+ FileUtils.deleteDirectory(dir);
+ }
+ }
- assertTrue(file.exists(),
- "Failed for " + file);
+ @Test
+ void testProvidedDirThreadLocal() throws IOException {
+ DefaultTempFileCreationStrategy parentStrategy = new DefaultTempFileCreationStrategy();
+ File dir = parentStrategy.createTempDirectory("testProvidedDir");
+ assertNotNull(dir, "Failed to create temp directory");
+ try {
+ assertTrue(Files.isDirectory(dir.toPath()), "File is not a directory: " + dir);
+ DefaultTempFileCreationStrategy testStrategy = new DefaultTempFileCreationStrategy(dir);
+ TempFile.setThreadLocalTempFileCreationStrategy(testStrategy);
+ checkGetFileAndPath(dir.toPath());
} finally {
- assertTrue(file.delete());
+ // Clean up the directory after the test
+ FileUtils.deleteDirectory(dir);
+ TempFile.setThreadLocalTempFileCreationStrategy(null);
+ }
+ }
+
+ @Test
+ void testProvidedDirNotExists() throws IOException {
+ DefaultTempFileCreationStrategy parentStrategy = new DefaultTempFileCreationStrategy();
+ File dir = parentStrategy.createTempDirectory("testProvidedDir");
+ assertNotNull(dir, "Failed to create temp directory");
+ assertTrue(dir.delete(), "directory not deleted: " + dir);
+ try {
+ DefaultTempFileCreationStrategy testStrategy = new DefaultTempFileCreationStrategy(dir);
+ checkGetFileAndPath(testStrategy, dir.toPath());
+ } finally {
+ // Clean up the directory after the test
+ FileUtils.deleteDirectory(dir);
+ }
+ }
+
+ @Test
+ void testProvidedDirIsActuallyAPlainFile() throws IOException {
+ DefaultTempFileCreationStrategy parentStrategy = new DefaultTempFileCreationStrategy();
+ File dir = parentStrategy.createTempFile("test123", ".tmp");
+ assertNotNull(dir, "Failed to create temp file");
+ try {
+ assertThrows(IllegalArgumentException.class, () -> new DefaultTempFileCreationStrategy(dir));
+ } finally {
+ dir.delete();
}
}
@@ -106,10 +155,11 @@ class DefaultTempFileCreationStrategyTest {
}
@Test
- void testCustomDir() throws IOException {
+ void testCustomDirExists() throws IOException {
File dirTest = File.createTempFile("POITest", ".dir");
try {
assertTrue(dirTest.delete());
+ assertTrue(dirTest.mkdir());
DefaultTempFileCreationStrategy strategy = new DefaultTempFileCreationStrategy(dirTest);
checkGetFile(strategy);
@@ -119,11 +169,12 @@ class DefaultTempFileCreationStrategyTest {
}
@Test
- void testCustomDirExists() throws IOException {
+ void testCustomDirAndPoiFilesExists() throws IOException {
File dirTest = File.createTempFile("POITest", ".dir");
try {
assertTrue(dirTest.delete());
assertTrue(dirTest.mkdir());
+ assertTrue(new File(dirTest, POIFILES).mkdir());
DefaultTempFileCreationStrategy strategy = new DefaultTempFileCreationStrategy(dirTest);
checkGetFile(strategy);
@@ -132,18 +183,35 @@ class DefaultTempFileCreationStrategyTest {
}
}
- @Test
- void testCustomDirAndPoiFilesExists() throws IOException {
- File dirTest = File.createTempFile("POITest", ".dir");
+ private static void checkGetFile(DefaultTempFileCreationStrategy strategy) throws IOException {
+ checkGetFileAndPath(strategy, null);
+ }
+
+ private static void checkGetFileAndPath(DefaultTempFileCreationStrategy strategy,
+ Path path) throws IOException {
+ File file = strategy.createTempFile("POITest", ".tmp");
+ testFileAndPath(file, path);
+ }
+
+ private static void checkGetFileAndPath(Path path) throws IOException {
+ File file = TempFile.createTempFile("POITest", ".tmp");
+ testFileAndPath(file, path);
+ }
+
+ private static void testFileAndPath(File file, Path path) throws IOException {
try {
- assertTrue(dirTest.delete());
- assertTrue(dirTest.mkdir());
- assertTrue(new File(dirTest, POIFILES).mkdir());
+ if (path != null) {
+ assertTrue(file.toPath().startsWith(path),
+ "File path does not start with expected path: " + path);
+ }
- DefaultTempFileCreationStrategy strategy = new DefaultTempFileCreationStrategy(dirTest);
- checkGetFile(strategy);
+ assertTrue(file.getParentFile().exists(),
+ "Failed for " + file.getParentFile());
+
+ assertTrue(file.exists(),
+ "Failed for " + file);
} finally {
- FileUtils.deleteDirectory(dirTest);
+ assertTrue(file.delete());
}
}
-} \ No newline at end of file
+}
diff --git a/poi/src/test/java/org/apache/poi/util/TestThreadLocalTempFile.java b/poi/src/test/java/org/apache/poi/util/TestThreadLocalTempFile.java
new file mode 100644
index 0000000000..86161e59ac
--- /dev/null
+++ b/poi/src/test/java/org/apache/poi/util/TestThreadLocalTempFile.java
@@ -0,0 +1,68 @@
+/* ====================================================================
+ 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 static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Path;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.RepeatedTest;
+import org.junit.jupiter.api.io.TempDir;
+
+class TestThreadLocalTempFile {
+ @AfterEach
+ void tearDown() {
+ TempFile.setTempFileCreationStrategy(new DefaultTempFileCreationStrategy());
+ }
+
+ @RepeatedTest(2) // Repeat it to ensure testing the case
+ void testThreadLocalStrategy(@TempDir Path tmpDir) {
+ Path rootDir = tmpDir.toAbsolutePath().normalize();
+ Path globalTmpDir = rootDir.resolve("global-tmp-dir");
+ Path localTmpDir1 = rootDir.resolve("local-tmp-dir1");
+ Path localTmpDir2 = rootDir.resolve("local-tmp-dir2");
+
+ TempFile.setTempFileCreationStrategy(new DefaultTempFileCreationStrategy(globalTmpDir.toFile()));
+ assertTempFileIn(globalTmpDir);
+
+ String result = TempFile.withStrategy(new DefaultTempFileCreationStrategy(localTmpDir1.toFile()), () -> {
+ assertTempFileIn(localTmpDir1);
+ String nestedResult = TempFile.withStrategy(new DefaultTempFileCreationStrategy(localTmpDir2.toFile()), () -> {
+ assertTempFileIn(localTmpDir2);
+ return "nested-test-result";
+ });
+ assertTempFileIn(localTmpDir1);
+ return "my-test-result-" + nestedResult;
+ });
+ assertTempFileIn(globalTmpDir);
+ assertEquals("my-test-result-nested-test-result", result);
+ }
+
+ private static void assertTempFileIn(Path expectedDir) {
+ Path tempFile;
+ try {
+ tempFile = TempFile.createTempFile("tmp-prefix", ".tmp").toPath();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ assertTrue(tempFile.startsWith(expectedDir), tempFile.toString());
+ }
+}