Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@

public class StringConverter extends DefaultTypeConverter {

/**
* Upper bound on the number of fraction digits emitted when formatting a number.
* <p>
* Covers every {@code double} and {@code float} value in full - the widest is
* {@link Double#MIN_VALUE} at 325 fraction digits - so the round-trip precision
* introduced by WW-4871 is preserved. Beyond that bound the length of the output
* would follow the scale of the value rather than its precision, so a
* {@link BigDecimal} scaled past this limit is rounded to it.
*/
private static final int MAX_FRACTION_DIGITS = 340;


@Override
public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType) {
String result;
Expand Down Expand Up @@ -86,7 +98,7 @@ protected String convertToString(Locale locale, Object value) {
// TODO: delete this variable and corresponding if statement when jdk fixed java.text.NumberFormat.format's behavior with Float
Object fixedValue = value;
if (BigDecimal.class.isInstance(value) || Double.class.isInstance(value) || Float.class.isInstance(value)) {
format.setMaximumFractionDigits(Integer.MAX_VALUE);
format.setMaximumFractionDigits(MAX_FRACTION_DIGITS);
if (Float.class.isInstance(value)) {
fixedValue = Double.valueOf(value.toString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.apache.struts2.StrutsInternalTestCase;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Locale;
import java.util.Map;

Expand Down Expand Up @@ -102,6 +103,18 @@
assertEquals(aBitBiggerThanDouble.substring(0, 309) + "," + aBitBiggerThanDouble.substring(310), value);
}

public void testBigDecimalFractionDigitsAreBounded() throws Exception {

Check warning on line 106 in core/src/test/java/com/opensymphony/xwork2/conversion/impl/StringConverterTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the declaration of thrown exception 'java.lang.Exception', as it cannot be thrown from method's body.

See more on https://sonarcloud.io/project/issues?id=apache_struts&issues=AaBZKeKNgEtsq8SiLtaD&open=AaBZKeKNgEtsq8SiLtaD&pullRequest=1888
// given
StringConverter converter = new StringConverter();
Map<String, Object> context = createContextWithLocale(new Locale("pl", "PL"));

// when the scale of the value exceeds the supported number of fraction digits
Object value = converter.convertValue(context, null, null, null, new BigDecimal(BigInteger.ONE, 100_000), null);

// then the length of the output is bounded by the converter, not by the scale of the value
assertEquals("0", value);
}

public void testStringArrayToStringConversion() {
// given
StringConverter converter = new StringConverter();
Expand Down
Loading