Skip to content

Commit 5a562cf

Browse files
authored
Add new ErrorReportConfiguration (#1067)
1 parent 817b775 commit 5a562cf

File tree

2 files changed

+329
-0
lines changed

2 files changed

+329
-0
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package com.fasterxml.jackson.core;
2+
3+
import java.io.Serializable;
4+
5+
/**
6+
* Container for configuration values used when handling errorneous token inputs.
7+
* For example, unquoted text segments.
8+
* <p>
9+
* Currently default settings are
10+
* <ul>
11+
* <li>Maximum length of token to include in error messages (see {@link #_maxErrorTokenLength})
12+
* <li>Maximum length of raw content to include in error messages (see {@link #_maxRawContentLength})
13+
* </ul>
14+
*
15+
* @since 2.16
16+
*/
17+
public class ErrorReportConfiguration
18+
implements Serializable {
19+
private static final long serialVersionUID = 1L;
20+
21+
/**
22+
* Default value for {@link #_maxErrorTokenLength}.
23+
*/
24+
public static final int DEFAULT_MAX_ERROR_TOKEN_LENGTH = 256;
25+
26+
/**
27+
* Previous was {@link com.fasterxml.jackson.core.io.ContentReference#DEFAULT_MAX_CONTENT_SNIPPET}.
28+
* Default value for {@link #_maxRawContentLength}.
29+
*/
30+
public static final int DEFAULT_MAX_RAW_CONTENT_LENGTH = 500;
31+
32+
/**
33+
* Maximum length of token to include in error messages
34+
*
35+
* @see Builder#maxErrorTokenLength(int)
36+
*/
37+
protected final int _maxErrorTokenLength;
38+
39+
/**
40+
* Maximum length of raw content to include in error messages
41+
*
42+
* @see Builder#maxRawContentLength(int)
43+
*/
44+
protected final int _maxRawContentLength;
45+
46+
private static ErrorReportConfiguration DEFAULT =
47+
new ErrorReportConfiguration(DEFAULT_MAX_ERROR_TOKEN_LENGTH, DEFAULT_MAX_RAW_CONTENT_LENGTH);
48+
49+
public static void overrideDefaultErrorReportConfiguration(final ErrorReportConfiguration errorReportConfiguration) {
50+
if (errorReportConfiguration == null) {
51+
DEFAULT = new ErrorReportConfiguration(DEFAULT_MAX_ERROR_TOKEN_LENGTH, DEFAULT_MAX_RAW_CONTENT_LENGTH);
52+
} else {
53+
DEFAULT = errorReportConfiguration;
54+
}
55+
}
56+
57+
/*
58+
/**********************************************************************
59+
/* Builder
60+
/**********************************************************************
61+
*/
62+
63+
public static final class Builder {
64+
private int maxErrorTokenLength;
65+
private int maxRawContentLength;
66+
67+
/**
68+
* @param maxErrorTokenLength Constraints
69+
* @return This factory instance (to allow call chaining)
70+
* @throws IllegalArgumentException if {@code maxErrorTokenLength} is less than 0
71+
*/
72+
public Builder maxErrorTokenLength(final int maxErrorTokenLength) {
73+
validateMaxErrorTokenLength(maxErrorTokenLength);
74+
this.maxErrorTokenLength = maxErrorTokenLength;
75+
return this;
76+
}
77+
78+
/**
79+
*
80+
* @see ErrorReportConfiguration#_maxRawContentLength
81+
* @return This factory instance (to allow call chaining)
82+
*/
83+
public Builder maxRawContentLength(final int maxRawContentLength) {
84+
validateMaxRawContentLength(maxRawContentLength);
85+
this.maxRawContentLength = maxRawContentLength;
86+
return this;
87+
}
88+
89+
Builder() {
90+
this(DEFAULT_MAX_ERROR_TOKEN_LENGTH, DEFAULT_MAX_RAW_CONTENT_LENGTH);
91+
}
92+
93+
Builder(final int maxErrorTokenLength, final int maxRawContentLength) {
94+
this.maxErrorTokenLength = maxErrorTokenLength;
95+
this.maxRawContentLength = maxRawContentLength;
96+
}
97+
98+
Builder(ErrorReportConfiguration src) {
99+
this.maxErrorTokenLength = src._maxErrorTokenLength;
100+
this.maxRawContentLength = src._maxRawContentLength;
101+
}
102+
103+
public ErrorReportConfiguration build() {
104+
return new ErrorReportConfiguration(maxErrorTokenLength, maxRawContentLength);
105+
}
106+
}
107+
108+
/*
109+
/**********************************************************************
110+
/* Life-cycle
111+
/**********************************************************************
112+
*/
113+
114+
protected ErrorReportConfiguration(final int maxErrorTokenLength, final int maxRawContentLength) {
115+
_maxErrorTokenLength = maxErrorTokenLength;
116+
_maxRawContentLength = maxRawContentLength;
117+
}
118+
119+
public static Builder builder() {
120+
return new Builder();
121+
}
122+
123+
/**
124+
* @return the default {@link ErrorReportConfiguration} (when none is set on the {@link JsonFactory} explicitly)
125+
* @see #overrideDefaultErrorReportConfiguration(ErrorReportConfiguration)
126+
*/
127+
public static ErrorReportConfiguration defaults() {
128+
return DEFAULT;
129+
}
130+
131+
/**
132+
* @return New {@link Builder} initialized with settings of configuration
133+
* instance
134+
*/
135+
public Builder rebuild() {
136+
return new Builder(this);
137+
}
138+
139+
/*
140+
/**********************************************************************
141+
/* Accessors
142+
/**********************************************************************
143+
*/
144+
145+
/**
146+
* Accessor for {@link #_maxErrorTokenLength}
147+
*
148+
* @return Maximum length of token to include in error messages
149+
* @see Builder#maxErrorTokenLength(int)
150+
*/
151+
public int getMaxErrorTokenLength() {
152+
return _maxErrorTokenLength;
153+
}
154+
155+
/**
156+
* Accessor for {@link #_maxRawContentLength}
157+
*
158+
* @return Maximum length of token to include in error messages
159+
* @see Builder#maxRawContentLength
160+
*/
161+
public int getMaxRawContentLength() {
162+
return _maxRawContentLength;
163+
}
164+
165+
/*
166+
/**********************************************************************
167+
/* Convenience methods for validation
168+
/**********************************************************************
169+
*/
170+
171+
/**
172+
* Convenience method that can be used verify valid {@link #_maxErrorTokenLength}.
173+
* If invalid value is passed in, {@link IllegalArgumentException} is thrown.
174+
*
175+
* @param maxErrorTokenLength Maximum length of token to include in error messages
176+
*/
177+
private static void validateMaxErrorTokenLength(int maxErrorTokenLength) throws IllegalArgumentException {
178+
if (maxErrorTokenLength < 0) {
179+
throw new IllegalArgumentException(
180+
String.format("Value of maxErrorTokenLength (%d) cannot be negative", maxErrorTokenLength));
181+
}
182+
}
183+
184+
private static void validateMaxRawContentLength(int maxRawContentLength) {
185+
if (maxRawContentLength < 0) {
186+
throw new IllegalArgumentException(
187+
String.format("Value of maxRawContentLength (%d) cannot be negative", maxRawContentLength));
188+
}
189+
}
190+
191+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package com.fasterxml.jackson.core;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.fail;
5+
import org.junit.jupiter.api.Test;
6+
7+
/**
8+
* Unit tests for class {@link ErrorReportConfiguration}.
9+
*
10+
* @since 2.16
11+
*/
12+
public class ErrorReportConfigurationTest
13+
{
14+
15+
private final ErrorReportConfiguration DEFAULTS = ErrorReportConfiguration.defaults();
16+
17+
@Test
18+
public void testNormalBuild()
19+
{
20+
ErrorReportConfiguration config = new ErrorReportConfiguration.Builder()
21+
.maxErrorTokenLength(1004)
22+
.maxRawContentLength(2008)
23+
.build();
24+
25+
assertEquals(1004, config.getMaxErrorTokenLength());
26+
assertEquals(2008, config.getMaxRawContentLength());
27+
}
28+
29+
@Test
30+
public void testZeroLengths()
31+
{
32+
// boundary tests, because we throw error on negative values
33+
ErrorReportConfiguration config = new ErrorReportConfiguration.Builder()
34+
.maxErrorTokenLength(0)
35+
.maxRawContentLength(0)
36+
.build();
37+
38+
assertEquals(0, config.getMaxErrorTokenLength());
39+
assertEquals(0, config.getMaxRawContentLength());
40+
}
41+
42+
@Test
43+
public void testInvalidMaxErrorTokenLength()
44+
{
45+
ErrorReportConfiguration.Builder builder = new ErrorReportConfiguration.Builder();
46+
47+
try {
48+
builder.maxErrorTokenLength(-1);
49+
fail("Should not reach here as exception is expected");
50+
} catch (IllegalArgumentException ex) {
51+
// expected
52+
}
53+
54+
try {
55+
builder.maxRawContentLength(-1);
56+
fail("Should not reach here as exception is expected");
57+
} catch (IllegalArgumentException ex) {
58+
// expected
59+
}
60+
}
61+
62+
@Test
63+
public void testDefaults()
64+
{
65+
// default value
66+
assertEquals(ErrorReportConfiguration.DEFAULT_MAX_ERROR_TOKEN_LENGTH, DEFAULTS.getMaxErrorTokenLength());
67+
assertEquals(ErrorReportConfiguration.DEFAULT_MAX_RAW_CONTENT_LENGTH, DEFAULTS.getMaxRawContentLength());
68+
69+
// equals
70+
assertEquals(ErrorReportConfiguration.defaults(), ErrorReportConfiguration.defaults());
71+
}
72+
73+
@Test
74+
public void testOverrideDefaultErrorReportConfiguration()
75+
{
76+
// (1) override with null, will be no change
77+
ErrorReportConfiguration.overrideDefaultErrorReportConfiguration(null);
78+
79+
ErrorReportConfiguration nullDefaults = ErrorReportConfiguration.defaults();
80+
81+
assertEquals(ErrorReportConfiguration.DEFAULT_MAX_ERROR_TOKEN_LENGTH, nullDefaults.getMaxErrorTokenLength());
82+
assertEquals(ErrorReportConfiguration.DEFAULT_MAX_RAW_CONTENT_LENGTH, nullDefaults.getMaxRawContentLength());
83+
84+
// (2) override wiht other value that actually changes default values
85+
ErrorReportConfiguration.overrideDefaultErrorReportConfiguration(new ErrorReportConfiguration.Builder()
86+
.maxErrorTokenLength(10101)
87+
.maxRawContentLength(20202)
88+
.build());
89+
90+
ErrorReportConfiguration overrideDefaults = ErrorReportConfiguration.defaults();
91+
92+
assertEquals(10101, overrideDefaults.getMaxErrorTokenLength());
93+
assertEquals(20202, overrideDefaults.getMaxRawContentLength());
94+
95+
// (3) revert back to default values
96+
// IMPORTANT : make sure to revert back, otherwise other tests will be affected
97+
ErrorReportConfiguration.overrideDefaultErrorReportConfiguration(new ErrorReportConfiguration.Builder()
98+
.maxErrorTokenLength(ErrorReportConfiguration.DEFAULT_MAX_ERROR_TOKEN_LENGTH)
99+
.maxRawContentLength(ErrorReportConfiguration.DEFAULT_MAX_RAW_CONTENT_LENGTH)
100+
.build());
101+
}
102+
103+
@Test
104+
public void testRebuild()
105+
{
106+
ErrorReportConfiguration config = new ErrorReportConfiguration.Builder().build();
107+
108+
ErrorReportConfiguration rebuiltConfig = config.rebuild().build();
109+
110+
assertEquals(config.getMaxErrorTokenLength(), rebuiltConfig.getMaxErrorTokenLength());
111+
assertEquals(config.getMaxRawContentLength(), rebuiltConfig.getMaxRawContentLength());
112+
}
113+
114+
115+
@Test
116+
public void testBuilderConstructorWithTwoParams()
117+
{
118+
ErrorReportConfiguration config = new ErrorReportConfiguration.Builder(1313, 2424)
119+
.build();
120+
121+
assertEquals(1313, config.getMaxErrorTokenLength());
122+
assertEquals(2424, config.getMaxRawContentLength());
123+
}
124+
125+
@Test
126+
public void testBuilderConstructorWithErrorReportConfiguration()
127+
{
128+
ErrorReportConfiguration configA = new ErrorReportConfiguration.Builder()
129+
.maxErrorTokenLength(1234)
130+
.maxRawContentLength(5678)
131+
.build();
132+
133+
ErrorReportConfiguration configB = new ErrorReportConfiguration.Builder(configA).build();
134+
135+
assertEquals(configA.getMaxErrorTokenLength(), configB.getMaxErrorTokenLength());
136+
assertEquals(configA.getMaxRawContentLength(), configB.getMaxRawContentLength());
137+
}
138+
}

0 commit comments

Comments
 (0)