Skip to content
Merged
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
7 changes: 7 additions & 0 deletions src/main/java/org/apache/xmlbeans/impl/common/XmlLocale.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.apache.xmlbeans.impl.common;

import org.apache.xmlbeans.XmlOptions;

public interface XmlLocale
{
boolean sync ( );
Expand All @@ -34,4 +36,9 @@ public interface XmlLocale
// (e.g. "1E5"), which is outside the xsd:decimal lexical space. Defaults to
// false (reject). Driven by XmlOptions.setLoadAllowDecimalExponent.
default boolean isLoadAllowDecimalExponent ( ) { return false; }

// the maximum number of characters a lexical number may have before it is
// rejected, applied when values are materialised from the store. Driven by
// XmlOptions.setMaxNumberOfCharsForNumbers.
default int getMaxNumberOfCharsForNumbers ( ) { return XmlOptions.DEFAULT_MAX_NUMBER_CHARS; }
}
8 changes: 8 additions & 0 deletions src/main/java/org/apache/xmlbeans/impl/store/Locale.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ private Locale(SchemaTypeLoader stl, XmlOptions options) {

_loadAllowDecimalExponent = options.isLoadAllowDecimalExponent();

_maxNumberOfChars = options.getMaxNumberOfCharsForNumbers();

//
// Check for Saaj implementation request
//
Expand Down Expand Up @@ -2083,6 +2085,10 @@ public boolean isLoadAllowDecimalExponent() {
return _loadAllowDecimalExponent;
}

public int getMaxNumberOfCharsForNumbers() {
return _maxNumberOfChars;
}

static boolean isWhiteSpace(String s) {
int l = s.length();

Expand Down Expand Up @@ -2805,6 +2811,8 @@ public QName getQName(char[] uriSrc, int uriPos, int uriCch,

boolean _loadAllowDecimalExponent;

int _maxNumberOfChars;

int _posTemp;

nthCache _nthCache_A = new nthCache();
Expand Down
47 changes: 41 additions & 6 deletions src/main/java/org/apache/xmlbeans/impl/util/MathUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,23 @@ public static BigDecimal parseAsBigDecimal(String s, int maxNumberOfChars) {
* @throws NullPointerException if string is null
*/
public static BigInteger parseAsBigInteger(String s) {
return parseAsBigInteger(s, DEFAULT_MAX_NUMBER_CHARS);
}

/**
* @param s string to parse
* @param maxNumberOfChars maximum number of characters allowed in the string
* @return valid BigInteger
* @throws NumberFormatException if parse fails
* @throws IllegalArgumentException if string is too long
* @throws NullPointerException if string is null
*/
public static BigInteger parseAsBigInteger(String s, int maxNumberOfChars) {
if (s == null) {
throw new NullPointerException("Cannot parse null as BigInteger");
}
if (s.length() > DEFAULT_MAX_NUMBER_CHARS) {
throw new IllegalArgumentException("Number has more than " + DEFAULT_MAX_NUMBER_CHARS + " characters");
if (s.length() > maxNumberOfChars) {
throw new IllegalArgumentException("Number has more than " + maxNumberOfChars + " characters");
}
return new BigInteger(s);
}
Expand Down Expand Up @@ -166,11 +178,23 @@ public static double parseAsDouble(String s, int maxNumberOfChars) {
* @throws NullPointerException if string is null
*/
public static long parseAsLong(String s) {
return parseAsLong(s, DEFAULT_MAX_NUMBER_CHARS);
}

/**
* @param s string to parse
* @param maxNumberOfChars maximum number of characters allowed in the string
* @return valid long
* @throws NumberFormatException if parse fails
* @throws IllegalArgumentException if string is too long
* @throws NullPointerException if string is null
*/
public static long parseAsLong(String s, int maxNumberOfChars) {
if (s == null) {
throw new NullPointerException("Cannot parse null as Long");
}
if (s.length() > DEFAULT_MAX_NUMBER_CHARS) {
throw new IllegalArgumentException("Number has more than " + DEFAULT_MAX_NUMBER_CHARS + " characters");
if (s.length() > maxNumberOfChars) {
throw new IllegalArgumentException("Number has more than " + maxNumberOfChars + " characters");
}
return Long.parseLong(s);
}
Expand Down Expand Up @@ -199,17 +223,28 @@ public static int parseAsInt(String s) {
* @throws NullPointerException if value is null
*/
public static BigInteger toBigInteger(BigDecimal value) {
return toBigInteger(value, DEFAULT_MAX_NUMBER_CHARS);
}

/**
* @param value BigDecimal to convert
* @param maxNumberOfChars maximum number of integer digits allowed in the value
* @return valid BigInteger
* @throws IllegalArgumentException if the input has an absolute exponent that is too large to safely convert
* @throws NullPointerException if value is null
*/
public static BigInteger toBigInteger(BigDecimal value, int maxNumberOfChars) {
if (value == null) {
throw new NullPointerException("Cannot convert null to BigInteger");
}
BigDecimal normalized = value.stripTrailingZeros();
int integerDigits = normalized.precision() - normalized.scale();
// the scale check is not redundant: for a very negative scale (eg 1E+2147483647) the
// subtraction above overflows and integerDigits comes out negative
if (integerDigits > DEFAULT_MAX_NUMBER_CHARS || normalized.scale() < -DEFAULT_MAX_NUMBER_CHARS) {
if (integerDigits > maxNumberOfChars || normalized.scale() < -maxNumberOfChars) {
throw new IllegalArgumentException(
"BigDecimal magnitude too large to convert safely: approx "
+ integerDigits + " integer digits (limit " + DEFAULT_MAX_NUMBER_CHARS + ")");
+ integerDigits + " integer digits (limit " + maxNumberOfChars + ")");
}
if (integerDigits <= 0) {
// abs(value) is less than 1, so it truncates to zero - avoid BigDecimal.toBigInteger()
Expand Down
45 changes: 42 additions & 3 deletions src/main/java/org/apache/xmlbeans/impl/util/XsTypeConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,21 @@ public static BigDecimal lexDecimal(CharSequence cs)
* @since 5.4.0
*/
public static BigDecimal lexDecimal(CharSequence cs, boolean allowExponent)
throws NumberFormatException {
return lexDecimal(cs, allowExponent, XmlOptions.DEFAULT_MAX_NUMBER_CHARS);
}

/**
* Parses an xsd:decimal lexical value.
*
* @param cs the lexical value
* @param allowExponent see {@link #lexDecimal(CharSequence, boolean)}
* @param maxNumberOfChars maximum number of characters allowed in the lexical value
* @return the parsed decimal
* @throws NumberFormatException if the value is not a valid xsd:decimal
* @since 5.4.1
*/
public static BigDecimal lexDecimal(CharSequence cs, boolean allowExponent, int maxNumberOfChars)
throws NumberFormatException {
rejectInvalidNumber(cs);
if (!allowExponent) {
Expand All @@ -252,7 +267,7 @@ public static BigDecimal lexDecimal(CharSequence cs, boolean allowExponent)
//equals() method, but the xml value
//space does not consider them significant.
//See http://www.w3.org/2001/05/xmlschema-errata#e2-44
return MathUtil.parseAsBigDecimal(trimTrailingZeros(v));
return MathUtil.parseAsBigDecimal(trimTrailingZeros(v), maxNumberOfChars);
}

private static final char[] CH_ZEROS = new char[]{'0', '0', '0', '0', '0', '0', '0', '0',
Expand Down Expand Up @@ -306,13 +321,25 @@ public static String printDecimal(BigDecimal value) {

// ======================== integer ========================
public static BigInteger lexInteger(CharSequence cs)
throws NumberFormatException {
return lexInteger(cs, XmlOptions.DEFAULT_MAX_NUMBER_CHARS);
}

/**
* @param cs the lexical value
* @param maxNumberOfChars maximum number of characters allowed in the lexical value
* @return the parsed integer
* @throws NumberFormatException if the value is not a valid xsd:integer
* @since 5.4.1
*/
public static BigInteger lexInteger(CharSequence cs, int maxNumberOfChars)
throws NumberFormatException {
rejectSignAfterPlus(cs);
final String v = cs.toString();

//TODO: consider special casing zero and one to return static values
//from BigInteger to avoid object creation.
return MathUtil.parseAsBigInteger(trimInitialPlus(v));
return MathUtil.parseAsBigInteger(trimInitialPlus(v), maxNumberOfChars);
}

public static BigInteger lexInteger(CharSequence cs, Collection<XmlError> errors) {
Expand All @@ -331,11 +358,23 @@ public static String printInteger(BigInteger value) {

// ======================== long ========================
public static long lexLong(CharSequence cs)
throws NumberFormatException {
return lexLong(cs, XmlOptions.DEFAULT_MAX_NUMBER_CHARS);
}

/**
* @param cs the lexical value
* @param maxNumberOfChars maximum number of characters allowed in the lexical value
* @return the parsed long
* @throws NumberFormatException if the value is not a valid xsd:long
* @since 5.4.1
*/
public static long lexLong(CharSequence cs, int maxNumberOfChars)
throws NumberFormatException {
rejectInvalidNumber(cs);
rejectSignAfterPlus(cs);
final String v = cs.toString();
return MathUtil.parseAsLong(trimInitialPlus(v));
return MathUtil.parseAsLong(trimInitialPlus(v), maxNumberOfChars);
}

// trimInitialPlus drops a single leading '+', then Long.parseLong /
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ protected String compute_text(NamespaceManager nsm) {

protected void set_text(String s) {
boolean allowExponent = has_store() && get_store().get_locale().isLoadAllowDecimalExponent();
int maxNumberOfChars = get_max_number_chars();
if (_validateOnSet()) {
validateLexical(s, _voorVc, allowExponent);
validateLexical(s, _voorVc, allowExponent, maxNumberOfChars);
}

try {
set_BigDecimal(MathUtil.parseAsBigDecimal(s));
set_BigDecimal(MathUtil.parseAsBigDecimal(s, maxNumberOfChars));
} catch (Exception e) {
_voorVc.invalid(XmlErrorCodes.DECIMAL, new Object[]{s});
}
Expand Down Expand Up @@ -162,7 +163,7 @@ protected int value_hash_code() {
}
}

BigInteger intval = MathUtil.toBigInteger(_value);
BigInteger intval = MathUtil.toBigInteger(_value, get_max_number_chars());

if (intval.compareTo(_maxlong) > 0 ||
intval.compareTo(_minlong) < 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,15 @@ public JavaDecimalHolderEx(SchemaType type, boolean complex) {
}

protected void set_text(String s) {
int maxNumberOfChars = get_max_number_chars();
if (_validateOnSet()) {
boolean allowExponent = has_store() && get_store().get_locale().isLoadAllowDecimalExponent();
validateLexical(s, _schemaType, _voorVc, allowExponent);
validateLexical(s, _schemaType, _voorVc, allowExponent, maxNumberOfChars);
}

BigDecimal v = null;
try {
v = MathUtil.parseAsBigDecimal(s);
v = MathUtil.parseAsBigDecimal(s, maxNumberOfChars);
} catch (Exception e) {
_voorVc.invalid(XmlErrorCodes.DECIMAL, new Object[]{s});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public int getIntValue() {

// setters
protected void set_BigDecimal(BigDecimal v) {
set_BigInteger(MathUtil.toBigInteger(v));
set_BigInteger(MathUtil.toBigInteger(v, get_max_number_chars()));
}

protected void set_BigInteger(BigInteger v) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlErrorCodes;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.common.QNameHelper;
import org.apache.xmlbeans.impl.common.ValidationContext;
import org.apache.xmlbeans.impl.util.MathUtil;
Expand Down Expand Up @@ -47,7 +48,7 @@ protected void set_text(String s) {

if (_validateOnSet()) {
validateValue(v, _schemaType, _voorVc);
validateLexical(s, _schemaType, _voorVc);
validateLexical(s, _schemaType, _voorVc, get_max_number_chars());
}

super.set_int(v);
Expand All @@ -62,7 +63,12 @@ protected void set_int(int v) {
}

public static void validateLexical(String v, SchemaType sType, ValidationContext context) {
JavaDecimalHolder.validateLexical(v, context);
validateLexical(v, sType, context, XmlOptions.DEFAULT_MAX_NUMBER_CHARS);
}

public static void validateLexical(String v, SchemaType sType, ValidationContext context,
int maxNumberOfChars) {
JavaDecimalHolder.validateLexical(v, context, false, maxNumberOfChars);

// check pattern
if (sType.hasPatternFacet()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.apache.xmlbeans.SimpleValue;
import org.apache.xmlbeans.XmlErrorCodes;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.common.ValidationContext;
import org.apache.xmlbeans.impl.schema.BuiltinSchemaTypeSystem;
import org.apache.xmlbeans.impl.util.MathUtil;
Expand All @@ -41,16 +42,20 @@ protected String compute_text(NamespaceManager nsm) {
}

protected void set_text(String s) {
set_BigInteger(lex(s, _voorVc));
set_BigInteger(lex(s, _voorVc, get_max_number_chars()));
}

public static BigInteger lex(String s, ValidationContext vc) {
return lex(s, vc, XmlOptions.DEFAULT_MAX_NUMBER_CHARS);
}

public static BigInteger lex(String s, ValidationContext vc, int maxNumberOfChars) {
if (!s.isEmpty() && s.charAt(0) == '+') {
s = s.substring(1);
}

try {
return MathUtil.parseAsBigInteger(s);
return MathUtil.parseAsBigInteger(s, maxNumberOfChars);
} catch (Exception e) {
vc.invalid(XmlErrorCodes.INTEGER, new Object[]{s});
return null;
Expand All @@ -74,7 +79,7 @@ public BigInteger getBigIntegerValue() {

// setters
protected void set_BigDecimal(BigDecimal v) {
_value = MathUtil.toBigInteger(v);
_value = MathUtil.toBigInteger(v, get_max_number_chars());
}

protected void set_BigInteger(BigInteger v) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlErrorCodes;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlPositiveInteger;
import org.apache.xmlbeans.impl.common.QNameHelper;
import org.apache.xmlbeans.impl.common.ValidationContext;
Expand All @@ -39,14 +40,15 @@ public SchemaType schemaType() {
}

protected void set_text(String s) {
BigInteger v = lex(s, _voorVc);
int maxNumberOfChars = get_max_number_chars();
BigInteger v = lex(s, _voorVc, maxNumberOfChars);

if (_validateOnSet()) {
validateValue(v, _schemaType, _voorVc);
}

if (_validateOnSet()) {
validateLexical(s, _schemaType, _voorVc);
validateLexical(s, _schemaType, _voorVc, maxNumberOfChars);
}

super.set_BigInteger(v);
Expand All @@ -61,7 +63,12 @@ protected void set_BigInteger(BigInteger v) {
}

public static void validateLexical(String v, SchemaType sType, ValidationContext context) {
JavaDecimalHolder.validateLexical(v, context);
validateLexical(v, sType, context, XmlOptions.DEFAULT_MAX_NUMBER_CHARS);
}

public static void validateLexical(String v, SchemaType sType, ValidationContext context,
int maxNumberOfChars) {
JavaDecimalHolder.validateLexical(v, context, false, maxNumberOfChars);
if (v.lastIndexOf('.') >= 0) {
context.invalid(XmlErrorCodes.INTEGER,
new Object[]{v});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ protected String compute_text(NamespaceManager nsm) {

protected void set_text(String s) {
try {
set_long(XsTypeConverter.lexLong(s));
set_long(XsTypeConverter.lexLong(s, get_max_number_chars()));
} catch (Exception e) {
throw new XmlValueOutOfRangeException(XmlErrorCodes.LONG, new Object[]{s});
}
Expand Down Expand Up @@ -73,7 +73,7 @@ public long getLongValue() {

// setters
protected void set_BigDecimal(BigDecimal v) {
set_BigInteger(MathUtil.toBigInteger(v));
set_BigInteger(MathUtil.toBigInteger(v, get_max_number_chars()));
}

protected void set_BigInteger(BigInteger v) {
Expand Down
Loading
Loading