Skip to content

Commit 3e27d96

Browse files
committed
Pull-up common Builder attributes to BaseNCodec
1 parent c29d6f7 commit 3e27d96

3 files changed

Lines changed: 104 additions & 53 deletions

File tree

src/main/java/org/apache/commons/codec/binary/Base32.java

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -288,14 +288,30 @@ public Base32(final int lineLength, final byte[] lineSeparator, final boolean us
288288
* @since 1.15
289289
*/
290290
public Base32(final int lineLength, final byte[] lineSeparator, final boolean useHex, final byte padding, final CodecPolicy decodingPolicy) {
291-
super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength, lineSeparator == null ? 0 : lineSeparator.length, padding, decodingPolicy);
292-
if (useHex) {
293-
this.encodeTable = HEX_ENCODE_TABLE;
294-
this.decodeTable = HEX_DECODE_TABLE;
295-
} else {
296-
this.encodeTable = ENCODE_TABLE;
297-
this.decodeTable = DECODE_TABLE;
298-
}
291+
this(lineLength, lineSeparator, useHex ? HEX_ENCODE_TABLE : ENCODE_TABLE, padding, decodingPolicy);
292+
}
293+
294+
/**
295+
* Constructs a Base32 / Base32 Hex codec used for decoding and encoding.
296+
* <p>
297+
* When encoding the line length and line separator are given in the constructor.
298+
* </p>
299+
* <p>
300+
* Line lengths that aren't multiples of 8 will still essentially end up being multiples of 8 in the encoded data.
301+
* </p>
302+
*
303+
* @param lineLength Each line of encoded data will be at most of the given length (rounded down to the nearest multiple of 8). If lineLength &lt;= 0,
304+
* then the output will not be divided into lines (chunks). Ignored when decoding.
305+
* @param lineSeparator Each line of encoded data will end with this sequence of bytes.
306+
* @param encodeTable A Base32 alphabet.
307+
* @param padding byte used as padding byte.
308+
* @param decodingPolicy The decoding policy.
309+
* @throws IllegalArgumentException Thrown when the {@code lineSeparator} contains Base32 characters. Or the lineLength &gt; 0 and lineSeparator is null.
310+
*/
311+
private Base32(final int lineLength, final byte[] lineSeparator, final byte[] encodeTable, final byte padding, final CodecPolicy decodingPolicy) {
312+
super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength, toLength(lineSeparator), padding, decodingPolicy);
313+
this.encodeTable = encodeTable;
314+
this.decodeTable = encodeTable == HEX_ENCODE_TABLE ? HEX_DECODE_TABLE : DECODE_TABLE;
299315
if (lineLength > 0) {
300316
if (lineSeparator == null) {
301317
throw new IllegalArgumentException("lineLength " + lineLength + " > 0, but lineSeparator is null");

src/main/java/org/apache/commons/codec/binary/Base64.java

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.math.BigInteger;
2121
import java.util.Arrays;
2222
import java.util.Objects;
23-
import java.util.function.Supplier;
2423

2524
import org.apache.commons.codec.CodecPolicy;
2625

@@ -62,27 +61,13 @@ public class Base64 extends BaseNCodec {
6261
*
6362
* @since 1.17.0
6463
*/
65-
public static class Builder implements Supplier<Base64> {
64+
public static class Builder extends AbstractBuilder<Base64, Builder> {
6665

67-
private int lineLength;
68-
private byte[] lineSeparator = CHUNK_SEPARATOR;
6966
private byte[] encodeTable = STANDARD_ENCODE_TABLE;
70-
private CodecPolicy decodingPolicy = DECODING_POLICY_DEFAULT;
7167

7268
@Override
7369
public Base64 get() {
74-
return new Base64(lineLength, lineSeparator, encodeTable, decodingPolicy);
75-
}
76-
77-
/**
78-
* Sets the decoding policy.
79-
*
80-
* @param decodingPolicy the decoding policy, null resets to the default.
81-
* @return this.
82-
*/
83-
public Builder setDecodingPolicy(final CodecPolicy decodingPolicy) {
84-
this.decodingPolicy = decodingPolicy != null ? decodingPolicy : DECODING_POLICY_DEFAULT;
85-
return this;
70+
return new Base64(getLineLength(), getLineSeparator(), encodeTable, getDecodingPolicy());
8671
}
8772

8873
/**
@@ -96,28 +81,6 @@ public Builder setEncodeTable(final byte... encodeTable) {
9681
return this;
9782
}
9883

99-
/**
100-
* Sets the line length.
101-
*
102-
* @param lineLength the line length, less than 0 resets to the default.
103-
* @return this.
104-
*/
105-
public Builder setLineLength(final int lineLength) {
106-
this.lineLength = Math.max(0, lineLength);
107-
return this;
108-
}
109-
110-
/**
111-
* Sets the line separator.
112-
*
113-
* @param lineSeparator the line separator, null resets to the default.
114-
* @return this.
115-
*/
116-
public Builder setLineSeparator(final byte... lineSeparator) {
117-
this.lineSeparator = lineSeparator != null ? lineSeparator : CHUNK_SEPARATOR;
118-
return this;
119-
}
120-
12184
/**
12285
* Sets the URL-safe encoding policy.
12386
*
@@ -561,6 +524,7 @@ public Base64(final boolean urlSafe) {
561524
this(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe);
562525
}
563526

527+
564528
/**
565529
* Constructs a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
566530
* <p>
@@ -584,7 +548,6 @@ public Base64(final int lineLength) {
584548
this(lineLength, CHUNK_SEPARATOR);
585549
}
586550

587-
588551
/**
589552
* Constructs a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
590553
* <p>
@@ -702,9 +665,8 @@ public Base64(final int lineLength, final byte[] lineSeparator, final boolean ur
702665
* Thrown when the {@code lineSeparator} contains Base64 characters.
703666
*/
704667
private Base64(final int lineLength, final byte[] lineSeparator, final byte[] encodeTable, final CodecPolicy decodingPolicy) {
705-
super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength, lineSeparator == null ? 0 : lineSeparator.length, PAD_DEFAULT, decodingPolicy);
668+
super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength, toLength(lineSeparator), PAD_DEFAULT, decodingPolicy);
706669
this.encodeTable = Objects.requireNonNull(encodeTable, "encodeTable");
707-
708670
if (encodeTable == STANDARD_ENCODE_TABLE || encodeTable == URL_SAFE_ENCODE_TABLE) {
709671
decodeTable = DECODE_TABLE;
710672
} else {

src/main/java/org/apache/commons/codec/binary/BaseNCodec.java

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.util.Arrays;
2121
import java.util.Objects;
22+
import java.util.function.Supplier;
2223

2324
import org.apache.commons.codec.BinaryDecoder;
2425
import org.apache.commons.codec.BinaryEncoder;
@@ -51,12 +52,75 @@
5152
*/
5253
public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
5354

55+
/**
56+
* Builds {@link Base64} instances.
57+
*
58+
* @param <T> the codec type to build.
59+
* @param <B> the codec builder subtype.
60+
* @since 1.17.0
61+
*/
62+
public abstract static class AbstractBuilder<T, B extends AbstractBuilder<T, B>> implements Supplier<T> {
63+
64+
private CodecPolicy decodingPolicy = DECODING_POLICY_DEFAULT;
65+
private int lineLength;
66+
private byte[] lineSeparator = CHUNK_SEPARATOR;
67+
68+
@SuppressWarnings("unchecked")
69+
B asThis() {
70+
return (B) this;
71+
}
72+
73+
CodecPolicy getDecodingPolicy() {
74+
return decodingPolicy;
75+
}
76+
77+
int getLineLength() {
78+
return lineLength;
79+
}
80+
81+
byte[] getLineSeparator() {
82+
return lineSeparator;
83+
}
84+
85+
/**
86+
* Sets the decoding policy.
87+
*
88+
* @param decodingPolicy the decoding policy, null resets to the default.
89+
* @return this.
90+
*/
91+
public B setDecodingPolicy(final CodecPolicy decodingPolicy) {
92+
this.decodingPolicy = decodingPolicy != null ? decodingPolicy : DECODING_POLICY_DEFAULT;
93+
return asThis();
94+
}
95+
96+
/**
97+
* Sets the line length.
98+
*
99+
* @param lineLength the line length, less than 0 resets to the default.
100+
* @return this.
101+
*/
102+
public B setLineLength(final int lineLength) {
103+
this.lineLength = Math.max(0, lineLength);
104+
return asThis();
105+
}
106+
107+
/**
108+
* Sets the line separator.
109+
*
110+
* @param lineSeparator the line separator, null resets to the default.
111+
* @return this.
112+
*/
113+
public B setLineSeparator(final byte... lineSeparator) {
114+
this.lineSeparator = lineSeparator != null ? lineSeparator : CHUNK_SEPARATOR;
115+
return asThis();
116+
}
117+
118+
}
119+
54120
/**
55121
* Holds thread context so classes can be thread-safe.
56122
*
57123
* This class is not itself thread-safe; each thread must allocate its own copy.
58-
*
59-
* @since 1.7
60124
*/
61125
static class Context {
62126

@@ -110,7 +174,6 @@ static class Context {
110174
*
111175
* @return a String useful for debugging.
112176
*/
113-
@SuppressWarnings("boxing") // OK to ignore boxing here
114177
@Override
115178
public String toString() {
116179
return String.format("%s[buffer=%s, currentLinePos=%s, eof=%s, ibitWorkArea=%s, lbitWorkArea=%s, " +
@@ -263,6 +326,16 @@ private static byte[] resizeBuffer(final Context context, final int minCapacity)
263326
return b;
264327
}
265328

329+
/**
330+
* Gets the array length or 0 if null.
331+
*
332+
* @param array the array or null.
333+
* @return the array length or 0 if null.
334+
*/
335+
static int toLength(final byte[] array) {
336+
return array == null ? 0 : array.length;
337+
}
338+
266339
/**
267340
* @deprecated Use {@link #pad}. Will be removed in 2.0.
268341
*/

0 commit comments

Comments
 (0)