All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fasterxml.jackson.core.Base64Variant Maven / Gradle / Ivy

Go to download

Core Jackson processing abstractions (aka Streaming API), implementation for JSON

There is a newer version: 2.17.0
Show newest version
/* Jackson JSON-processor.
 *
 * Copyright (c) 2007- Tatu Saloranta, [email protected]
 */
package com.fasterxml.jackson.core;

import java.util.Arrays;

import com.fasterxml.jackson.core.util.ByteArrayBuilder;

/**
 * Class used to define specific details of which
 * variant of Base64 encoding/decoding is to be used. Although there is
 * somewhat standard basic version (so-called "MIME Base64"), other variants
 * exists, see Base64 Wikipedia entry for details.
 * 
 * @author Tatu Saloranta
 */
public final class Base64Variant
    implements java.io.Serializable
{
    /**
     * Defines how the Base64Variant deals with Padding while reading
     *
     * @since 2.12
     */
    public enum PaddingReadBehaviour {
        /**
         * Padding is not allowed in Base64 content being read (finding something
         * that looks like padding at the end of content results in an exception)
         */
        PADDING_FORBIDDEN,

        /**
         * Padding is required in Base64 content being read
         * (missing padding for incomplete ending quartet results in an exception)
         */
        PADDING_REQUIRED,

        /**
         * Padding is allowed but not required in Base64 content being read: no
         * exception thrown based on existence or absence, as long as proper
         * padding characters are used.
         */
        PADDING_ALLOWED
        ;
    }

    private final static int INT_SPACE = 0x20;
    
    // We'll only serialize name
    private static final long serialVersionUID = 1L;

    /**
     * Placeholder used by "no padding" variant, to be used when a character
     * value is needed.
     */
    protected final static char PADDING_CHAR_NONE = '\0';

    /**
     * Marker used to denote ascii characters that do not correspond
     * to a 6-bit value (in this variant), and is not used as a padding
     * character.
     */
    public final static int BASE64_VALUE_INVALID = -1;

    /**
     * Marker used to denote ascii character (in decoding table) that
     * is the padding character using this variant (if any).
     */
    public final static int BASE64_VALUE_PADDING = -2;

    /*
    /**********************************************************
    /* Encoding/decoding tables
    /**********************************************************
     */

    /**
     * Decoding table used for base 64 decoding.
     */
    private final transient int[] _asciiToBase64 = new int[128];

    /**
     * Encoding table used for base 64 decoding when output is done
     * as characters.
     */
    private final transient char[] _base64ToAsciiC = new char[64];

    /**
     * Alternative encoding table used for base 64 decoding when output is done
     * as ascii bytes.
     */
    private final transient byte[] _base64ToAsciiB = new byte[64];

    /*
    /**********************************************************
    /* Other configuration
    /**********************************************************
     */

    /**
     * Symbolic name of variant; used for diagnostics/debugging.
     *

* Note that this is the only non-transient field; used when reading * back from serialized state. *

* Also: must not be private, accessed from `BaseVariants` */ final String _name; /** * Character used for padding, if any ({@link #PADDING_CHAR_NONE} if not). */ private final char _paddingChar; /** * Maximum number of encoded base64 characters to output during encoding * before adding a linefeed, if line length is to be limited * ({@link java.lang.Integer#MAX_VALUE} if not limited). *

* Note: for some output modes (when writing attributes) linefeeds may * need to be avoided, and this value ignored. */ private final int _maxLineLength; /** * Whether this variant uses padding when writing out content or not. * * @since 2.12 */ private final boolean _writePadding; /** * Whether padding characters should be required or not while decoding * * @since 2.12 */ private final PaddingReadBehaviour _paddingReadBehaviour; /* /********************************************************** /* Life-cycle /********************************************************** */ public Base64Variant(String name, String base64Alphabet, boolean writePadding, char paddingChar, int maxLineLength) { _name = name; _writePadding = writePadding; _paddingChar = paddingChar; _maxLineLength = maxLineLength; // Ok and then we need to create codec tables. // First the main encoding table: int alphaLen = base64Alphabet.length(); if (alphaLen != 64) { throw new IllegalArgumentException("Base64Alphabet length must be exactly 64 (was "+alphaLen+")"); } // And then secondary encoding table and decoding table: base64Alphabet.getChars(0, alphaLen, _base64ToAsciiC, 0); Arrays.fill(_asciiToBase64, BASE64_VALUE_INVALID); for (int i = 0; i < alphaLen; ++i) { char alpha = _base64ToAsciiC[i]; _base64ToAsciiB[i] = (byte) alpha; _asciiToBase64[alpha] = i; } // Plus if we use padding, add that in too if (writePadding) { _asciiToBase64[(int) paddingChar] = BASE64_VALUE_PADDING; } // By default, require padding on input if written on output; do not // accept if padding not written _paddingReadBehaviour = writePadding ? PaddingReadBehaviour.PADDING_REQUIRED : PaddingReadBehaviour.PADDING_FORBIDDEN; } /** * "Copy constructor" that can be used when the base alphabet is identical * to one used by another variant except for the maximum line length * (and obviously, name). * * @param base Variant to use for settings not specific by other parameters * @param name Name of this variant * @param maxLineLength Maximum length (in characters) of lines to output before * using linefeed */ public Base64Variant(Base64Variant base, String name, int maxLineLength) { this(base, name, base._writePadding, base._paddingChar, maxLineLength); } /** * "Copy constructor" that can be used when the base alphabet is identical * to one used by another variant, but other details (padding, maximum * line length) differ * * @param base Variant to use for settings not specific by other parameters * @param name Name of this variant * @param writePadding Whether variant will use padding when encoding * @param paddingChar Padding character used for encoding, excepted on reading, if any * @param maxLineLength Maximum length (in characters) of lines to output before * using linefeed */ public Base64Variant(Base64Variant base, String name, boolean writePadding, char paddingChar, int maxLineLength) { this(base, name, writePadding, paddingChar, base._paddingReadBehaviour, maxLineLength); } private Base64Variant(Base64Variant base, String name, boolean writePadding, char paddingChar, PaddingReadBehaviour paddingReadBehaviour, int maxLineLength) { _name = name; byte[] srcB = base._base64ToAsciiB; System.arraycopy(srcB, 0, this._base64ToAsciiB, 0, srcB.length); char[] srcC = base._base64ToAsciiC; System.arraycopy(srcC, 0, this._base64ToAsciiC, 0, srcC.length); int[] srcV = base._asciiToBase64; System.arraycopy(srcV, 0, this._asciiToBase64, 0, srcV.length); _writePadding = writePadding; _paddingChar = paddingChar; _maxLineLength = maxLineLength; _paddingReadBehaviour = paddingReadBehaviour; } private Base64Variant(Base64Variant base, PaddingReadBehaviour paddingReadBehaviour) { this(base, base._name, base._writePadding, base._paddingChar, paddingReadBehaviour, base._maxLineLength); } /** * @return Base64Variant which does not require padding on read * * @since 2.12 */ public Base64Variant withPaddingAllowed() { return withReadPadding(PaddingReadBehaviour.PADDING_ALLOWED); } /** * @return Base64Variant which requires padding on read * @since 2.12 */ public Base64Variant withPaddingRequired() { return withReadPadding(PaddingReadBehaviour.PADDING_REQUIRED); } /** * @return Base64Variant which does not accept padding on read * @since 2.12 */ public Base64Variant withPaddingForbidden() { return withReadPadding(PaddingReadBehaviour.PADDING_FORBIDDEN); } /** * @param readPadding Padding read behavior desired * * @return Instance with desired padding read behavior setting (this * if already has setting; new instance otherwise) * * @since 2.12 */ public Base64Variant withReadPadding(PaddingReadBehaviour readPadding) { return (readPadding == _paddingReadBehaviour) ? this : new Base64Variant(this, readPadding); } /** * @param writePadding Determines if padding is output on write or not * * @return Base64Variant which writes padding or not depending on writePadding * * @since 2.12 */ public Base64Variant withWritePadding(boolean writePadding) { return (writePadding == _writePadding) ? this : new Base64Variant(this, _name, writePadding, _paddingChar, _maxLineLength); } /* /********************************************************** /* Serializable overrides /********************************************************** */ // 26-Oct-2020, tatu: Much more complicated with 2.12 as it is // possible to create differently configured instances. // Need to start with name to regenerate tables etc but then // handle overrides protected Object readResolve() { Base64Variant base = Base64Variants.valueOf(_name); if ((_writePadding != base._writePadding) || (_paddingChar != base._paddingChar) || (_paddingReadBehaviour != base._paddingReadBehaviour) || (_maxLineLength != base._maxLineLength) || (_writePadding != base._writePadding) ) { return new Base64Variant(base, _name, _writePadding, _paddingChar, _paddingReadBehaviour, _maxLineLength); } return base; } /* /********************************************************** /* Public accessors /********************************************************** */ public String getName() { return _name; } /** * @return True if this Base64 encoding will write padding on output * (note: before Jackson 2.12 also dictated whether padding was accepted on read) */ public boolean usesPadding() { return _writePadding; } /** * @return {@code True} if this variant requires padding on content decoded; {@code false} if not. * * @since 2.12 */ public boolean requiresPaddingOnRead() { return _paddingReadBehaviour == PaddingReadBehaviour.PADDING_REQUIRED; } /** * @return {@code True} if this variant accepts padding on content decoded; {@code false} if not. * * @since 2.12 */ public boolean acceptsPaddingOnRead() { return _paddingReadBehaviour != PaddingReadBehaviour.PADDING_FORBIDDEN; } public boolean usesPaddingChar(char c) { return c == _paddingChar; } public boolean usesPaddingChar(int ch) { return ch == (int) _paddingChar; } /** * @return Indicator on how this Base64 encoding will handle possible padding * in content when reading. * * @since 2.12 */ public PaddingReadBehaviour paddingReadBehaviour() { return _paddingReadBehaviour; } public char getPaddingChar() { return _paddingChar; } public byte getPaddingByte() { return (byte)_paddingChar; } public int getMaxLineLength() { return _maxLineLength; } /* /********************************************************** /* Decoding support /********************************************************** */ /** * @param c Character to decode * * @return 6-bit decoded value, if valid character; */ public int decodeBase64Char(char c) { int ch = (int) c; return (ch <= 127) ? _asciiToBase64[ch] : BASE64_VALUE_INVALID; } public int decodeBase64Char(int ch) { return (ch <= 127) ? _asciiToBase64[ch] : BASE64_VALUE_INVALID; } public int decodeBase64Byte(byte b) { int ch = (int) b; // note: cast retains sign, so it's from -128 to +127 if (ch < 0) { return BASE64_VALUE_INVALID; } return _asciiToBase64[ch]; } /* /********************************************************** /* Encoding support /********************************************************** */ public char encodeBase64BitsAsChar(int value) { // Let's assume caller has done necessary checks; this // method must be fast and inlinable return _base64ToAsciiC[value]; } /** * Method that encodes given right-aligned (LSB) 24-bit value * into 4 base64 characters, stored in given result buffer. * Caller must ensure there is sufficient space for 4 encoded characters * at specified position. * * @param b24 3-byte value to encode * @param buffer Output buffer to append characters to * @param outPtr Starting position within {@code buffer} to append encoded characters * * @return Pointer in output buffer after appending 4 encoded characters */ public int encodeBase64Chunk(int b24, char[] buffer, int outPtr) { buffer[outPtr++] = _base64ToAsciiC[(b24 >> 18) & 0x3F]; buffer[outPtr++] = _base64ToAsciiC[(b24 >> 12) & 0x3F]; buffer[outPtr++] = _base64ToAsciiC[(b24 >> 6) & 0x3F]; buffer[outPtr++] = _base64ToAsciiC[b24 & 0x3F]; return outPtr; } public void encodeBase64Chunk(StringBuilder sb, int b24) { sb.append(_base64ToAsciiC[(b24 >> 18) & 0x3F]); sb.append(_base64ToAsciiC[(b24 >> 12) & 0x3F]); sb.append(_base64ToAsciiC[(b24 >> 6) & 0x3F]); sb.append(_base64ToAsciiC[b24 & 0x3F]); } /** * Method that outputs partial chunk (which only encodes one * or two bytes of data). Data given is still aligned same as if * it as full data; that is, missing data is at the "right end" * (LSB) of int. * * @param bits 24-bit chunk containing 1 or 2 bytes to encode * @param outputBytes Number of input bytes to encode (either 1 or 2) * @param buffer Output buffer to append characters to * @param outPtr Starting position within {@code buffer} to append encoded characters * * @return Pointer in output buffer after appending encoded characters (2, 3 or 4) */ public int encodeBase64Partial(int bits, int outputBytes, char[] buffer, int outPtr) { buffer[outPtr++] = _base64ToAsciiC[(bits >> 18) & 0x3F]; buffer[outPtr++] = _base64ToAsciiC[(bits >> 12) & 0x3F]; if (usesPadding()) { buffer[outPtr++] = (outputBytes == 2) ? _base64ToAsciiC[(bits >> 6) & 0x3F] : _paddingChar; buffer[outPtr++] = _paddingChar; } else { if (outputBytes == 2) { buffer[outPtr++] = _base64ToAsciiC[(bits >> 6) & 0x3F]; } } return outPtr; } public void encodeBase64Partial(StringBuilder sb, int bits, int outputBytes) { sb.append(_base64ToAsciiC[(bits >> 18) & 0x3F]); sb.append(_base64ToAsciiC[(bits >> 12) & 0x3F]); if (usesPadding()) { sb.append((outputBytes == 2) ? _base64ToAsciiC[(bits >> 6) & 0x3F] : _paddingChar); sb.append(_paddingChar); } else { if (outputBytes == 2) { sb.append(_base64ToAsciiC[(bits >> 6) & 0x3F]); } } } public byte encodeBase64BitsAsByte(int value) { // As with above, assuming it is 6-bit value return _base64ToAsciiB[value]; } /** * Method that encodes given right-aligned (LSB) 24-bit value * into 4 base64 bytes (ascii), stored in given result buffer. * * @param b24 3-byte value to encode * @param buffer Output buffer to append characters (as bytes) to * @param outPtr Starting position within {@code buffer} to append encoded characters * * @return Pointer in output buffer after appending 4 encoded characters */ public int encodeBase64Chunk(int b24, byte[] buffer, int outPtr) { buffer[outPtr++] = _base64ToAsciiB[(b24 >> 18) & 0x3F]; buffer[outPtr++] = _base64ToAsciiB[(b24 >> 12) & 0x3F]; buffer[outPtr++] = _base64ToAsciiB[(b24 >> 6) & 0x3F]; buffer[outPtr++] = _base64ToAsciiB[b24 & 0x3F]; return outPtr; } /** * Method that outputs partial chunk (which only encodes one * or two bytes of data). Data given is still aligned same as if * it as full data; that is, missing data is at the "right end" * (LSB) of int. * * @param bits 24-bit chunk containing 1 or 2 bytes to encode * @param outputBytes Number of input bytes to encode (either 1 or 2) * @param buffer Output buffer to append characters to * @param outPtr Starting position within {@code buffer} to append encoded characters * * @return Pointer in output buffer after appending encoded characters (2, 3 or 4) */ public int encodeBase64Partial(int bits, int outputBytes, byte[] buffer, int outPtr) { buffer[outPtr++] = _base64ToAsciiB[(bits >> 18) & 0x3F]; buffer[outPtr++] = _base64ToAsciiB[(bits >> 12) & 0x3F]; if (usesPadding()) { byte pb = (byte) _paddingChar; buffer[outPtr++] = (outputBytes == 2) ? _base64ToAsciiB[(bits >> 6) & 0x3F] : pb; buffer[outPtr++] = pb; } else { if (outputBytes == 2) { buffer[outPtr++] = _base64ToAsciiB[(bits >> 6) & 0x3F]; } } return outPtr; } /* /********************************************************** /* Convenience conversion methods for String to/from bytes use case /********************************************************** */ /** * Convenience method for converting given byte array as base64 encoded * String using this variant's settings. * Resulting value is "raw", that is, not enclosed in double-quotes. * * @param input Byte array to encode * * @return Base64 encoded String of encoded {@code input} bytes, not surrounded by quotes */ public String encode(byte[] input) { return encode(input, false); } /** * Convenience method for converting given byte array as base64 encoded String * using this variant's settings, optionally enclosed in double-quotes. * Linefeeds added, if needed, are expressed as 2-character JSON (and Java source) * escape sequence of backslash + `n`. * * @param input Byte array to encode * @param addQuotes Whether to surround resulting value in double quotes or not * * @return Base64 encoded String of encoded {@code input} bytes, possibly * surrounded by quotes (if {@code addQuotes} enabled) */ public String encode(byte[] input, boolean addQuotes) { final int inputEnd = input.length; final StringBuilder sb = new StringBuilder(inputEnd + (inputEnd >> 2) + (inputEnd >> 3)); if (addQuotes) { sb.append('"'); } int chunksBeforeLF = getMaxLineLength() >> 2; // Ok, first we loop through all full triplets of data: int inputPtr = 0; int safeInputEnd = inputEnd-3; // to get only full triplets while (inputPtr <= safeInputEnd) { // First, mash 3 bytes into lsb of 32-bit int int b24 = ((int) input[inputPtr++]) << 8; b24 |= ((int) input[inputPtr++]) & 0xFF; b24 = (b24 << 8) | (((int) input[inputPtr++]) & 0xFF); encodeBase64Chunk(sb, b24); if (--chunksBeforeLF <= 0) { // note: must quote in JSON value, so not really useful... sb.append('\\'); sb.append('n'); chunksBeforeLF = getMaxLineLength() >> 2; } } // And then we may have 1 or 2 leftover bytes to encode int inputLeft = inputEnd - inputPtr; // 0, 1 or 2 if (inputLeft > 0) { // yes, but do we have room for output? int b24 = ((int) input[inputPtr++]) << 16; if (inputLeft == 2) { b24 |= (((int) input[inputPtr++]) & 0xFF) << 8; } encodeBase64Partial(sb, b24, inputLeft); } if (addQuotes) { sb.append('"'); } return sb.toString(); } /** * Convenience method for converting given byte array as base64 encoded String * using this variant's settings, optionally enclosed in double-quotes. * Linefeed character to use is passed explicitly. * * @param input Byte array to encode * @param addQuotes Whether to surround resulting value in double quotes or not * @param linefeed Linefeed to use for encoded content * * @return Base64 encoded String of encoded {@code input} bytes * * @since 2.10 */ public String encode(byte[] input, boolean addQuotes, String linefeed) { final int inputEnd = input.length; final StringBuilder sb = new StringBuilder(inputEnd + (inputEnd >> 2) + (inputEnd >> 3)); if (addQuotes) { sb.append('"'); } int chunksBeforeLF = getMaxLineLength() >> 2; int inputPtr = 0; int safeInputEnd = inputEnd-3; while (inputPtr <= safeInputEnd) { int b24 = ((int) input[inputPtr++]) << 8; b24 |= ((int) input[inputPtr++]) & 0xFF; b24 = (b24 << 8) | (((int) input[inputPtr++]) & 0xFF); encodeBase64Chunk(sb, b24); if (--chunksBeforeLF <= 0) { sb.append(linefeed); chunksBeforeLF = getMaxLineLength() >> 2; } } int inputLeft = inputEnd - inputPtr; if (inputLeft > 0) { int b24 = ((int) input[inputPtr++]) << 16; if (inputLeft == 2) { b24 |= (((int) input[inputPtr++]) & 0xFF) << 8; } encodeBase64Partial(sb, b24, inputLeft); } if (addQuotes) { sb.append('"'); } return sb.toString(); } /** * Convenience method for decoding contents of a Base64-encoded String, * using this variant's settings. * * @param input Base64-encoded input String to decode * * @return Byte array of decoded contents * * @since 2.3 * * @throws IllegalArgumentException if input is not valid base64 encoded data */ @SuppressWarnings("resource") public byte[] decode(String input) throws IllegalArgumentException { ByteArrayBuilder b = new ByteArrayBuilder(); decode(input, b); return b.toByteArray(); } /** * Convenience method for decoding contents of a Base64-encoded String, * using this variant's settings * and appending decoded binary data using provided {@link ByteArrayBuilder}. *

* NOTE: builder will NOT be reset before decoding (nor cleared afterwards); * assumption is that caller will ensure it is given in proper state, and * used as appropriate afterwards. * * @param str Input to decode * @param builder Builder used for assembling decoded content * * @since 2.3 * * @throws IllegalArgumentException if input is not valid base64 encoded data */ public void decode(String str, ByteArrayBuilder builder) throws IllegalArgumentException { int ptr = 0; int len = str.length(); main_loop: while (true) { // first, we'll skip preceding white space, if any char ch; do { if (ptr >= len) { break main_loop; } ch = str.charAt(ptr++); } while (ch <= INT_SPACE); int bits = decodeBase64Char(ch); if (bits < 0) { _reportInvalidBase64(ch, 0, null); } int decodedData = bits; // then second base64 char; can't get padding yet, nor ws if (ptr >= len) { _reportBase64EOF(); } ch = str.charAt(ptr++); bits = decodeBase64Char(ch); if (bits < 0) { _reportInvalidBase64(ch, 1, null); } decodedData = (decodedData << 6) | bits; // third base64 char; can be padding, but not ws if (ptr >= len) { // but as per [JACKSON-631] can be end-of-input, iff padding is not required if (!requiresPaddingOnRead()) { decodedData >>= 4; builder.append(decodedData); break; } _reportBase64EOF(); } ch = str.charAt(ptr++); bits = decodeBase64Char(ch); // First branch: can get padding (-> 1 byte) if (bits < 0) { if (bits != Base64Variant.BASE64_VALUE_PADDING) { _reportInvalidBase64(ch, 2, null); } if (!acceptsPaddingOnRead()) { _reportBase64UnexpectedPadding(); } // Ok, must get padding if (ptr >= len) { _reportBase64EOF(); } ch = str.charAt(ptr++); if (!usesPaddingChar(ch)) { _reportInvalidBase64(ch, 3, "expected padding character '"+getPaddingChar()+"'"); } // Got 12 bits, only need 8, need to shift decodedData >>= 4; builder.append(decodedData); continue; } // Nope, 2 or 3 bytes decodedData = (decodedData << 6) | bits; // fourth and last base64 char; can be padding, but not ws if (ptr >= len) { // but as per [JACKSON-631] can be end-of-input, iff padding on read is not required if (!requiresPaddingOnRead()) { decodedData >>= 2; builder.appendTwoBytes(decodedData); break; } _reportBase64EOF(); } ch = str.charAt(ptr++); bits = decodeBase64Char(ch); if (bits < 0) { if (bits != Base64Variant.BASE64_VALUE_PADDING) { _reportInvalidBase64(ch, 3, null); } if (!acceptsPaddingOnRead()) { _reportBase64UnexpectedPadding(); } decodedData >>= 2; builder.appendTwoBytes(decodedData); } else { // otherwise, our triple is now complete decodedData = (decodedData << 6) | bits; builder.appendThreeBytes(decodedData); } } } /* /********************************************************** /* Overridden standard methods /********************************************************** */ @Override public String toString() { return _name; } @Override public boolean equals(Object o) { // identity comparison should be fine // 26-Oct-2020, tatu: ... not any more with 2.12 if (o == this) return true; if (o == null || o.getClass() != getClass()) return false; Base64Variant other = (Base64Variant) o; return (other._paddingChar == _paddingChar) && (other._maxLineLength == _maxLineLength) && (other._writePadding == _writePadding) && (other._paddingReadBehaviour == _paddingReadBehaviour) && (_name.equals(other._name)) ; } @Override public int hashCode() { return _name.hashCode(); } /* /********************************************************** /* Internal helper methods /********************************************************** */ /** * @param ch Character to report on * @param bindex Relative index within base64 character unit; between 0 * and 3 (as unit has exactly 4 characters) * @param msg Base message to use for exception */ protected void _reportInvalidBase64(char ch, int bindex, String msg) throws IllegalArgumentException { String base; if (ch <= INT_SPACE) { base = "Illegal white space character (code 0x"+Integer.toHexString(ch)+") as character #"+(bindex+1)+" of 4-char base64 unit: can only used between units"; } else if (usesPaddingChar(ch)) { base = "Unexpected padding character ('"+getPaddingChar()+"') as character #"+(bindex+1)+" of 4-char base64 unit: padding only legal as 3rd or 4th character"; } else if (!Character.isDefined(ch) || Character.isISOControl(ch)) { // Not sure if we can really get here... ? (most illegal xml chars are caught at lower level) base = "Illegal character (code 0x"+Integer.toHexString(ch)+") in base64 content"; } else { base = "Illegal character '"+ch+"' (code 0x"+Integer.toHexString(ch)+") in base64 content"; } if (msg != null) { base = base + ": " + msg; } throw new IllegalArgumentException(base); } protected void _reportBase64EOF() throws IllegalArgumentException { throw new IllegalArgumentException(missingPaddingMessage()); } protected void _reportBase64UnexpectedPadding() throws IllegalArgumentException { throw new IllegalArgumentException(unexpectedPaddingMessage()); } /** * Helper method that will construct a message to use in exceptions for cases where input ends * prematurely in place where padding is not expected. * * @return Exception message for indicating "unexpected padding" case * * @since 2.12 */ protected String unexpectedPaddingMessage() { return String.format("Unexpected end of base64-encoded String: base64 variant '%s' expects no padding at the end while decoding. This Base64Variant might have been incorrectly configured", getName()); } /** * Helper method that will construct a message to use in exceptions for cases where input ends * prematurely in place where padding would be expected. * * @return Exception message for indicating "missing padding" case * * @since 2.10 */ public String missingPaddingMessage() { // !!! TODO: why is this 'public'? return String.format("Unexpected end of base64-encoded String: base64 variant '%s' expects padding (one or more '%c' characters) at the end. This Base64Variant might have been incorrectly configured", getName(), getPaddingChar()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy