|
18 | 18 |
|
19 | 19 | import java.nio.charset.Charset;
|
20 | 20 | import java.util.Base64;
|
| 21 | + |
21 | 22 | import javax.xml.bind.DatatypeConverter;
|
22 | 23 |
|
23 | 24 | import org.springframework.lang.UsesJava8;
|
|
30 | 31 | * Codec present, {@link #encode}/{@link #decode} calls will throw an IllegalStateException.
|
31 | 32 | * However, as of Spring 4.2, {@link #encodeToString} and {@link #decodeFromString} will
|
32 | 33 | * nevertheless work since they can delegate to the JAXB DatatypeConverter as a fallback.
|
| 34 | + * However, this does not apply when using the ...UrlSafe... methods for RFC 4648 "URL and |
| 35 | + * Filename Safe Alphabet"; a delegate is required. |
| 36 | + * <p> |
| 37 | + * <em>Note:</em> Apache Commons Codec does not add padding ({@code =}) when encoding with |
| 38 | + * the URL and Filename Safe Alphabet. |
33 | 39 | *
|
34 | 40 | * @author Juergen Hoeller
|
| 41 | + * @author Gary Russell |
35 | 42 | * @since 4.1
|
36 | 43 | * @see java.util.Base64
|
37 | 44 | * @see org.apache.commons.codec.binary.Base64
|
@@ -92,6 +99,32 @@ public static byte[] decode(byte[] src) {
|
92 | 99 | return delegate.decode(src);
|
93 | 100 | }
|
94 | 101 |
|
| 102 | + /** |
| 103 | + * Base64-encode the given byte array using the RFC 4868 |
| 104 | + * "URL and Filename Safe Alphabet". |
| 105 | + * @param src the original byte array (may be {@code null}) |
| 106 | + * @return the encoded byte array (or {@code null} if the input was {@code null}) |
| 107 | + * @throws IllegalStateException if Base64 encoding between byte arrays is not |
| 108 | + * supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime |
| 109 | + */ |
| 110 | + public static byte[] encodeUrlSafe(byte[] src) { |
| 111 | + assertDelegateAvailable(); |
| 112 | + return delegate.encodeUrlSafe(src); |
| 113 | + } |
| 114 | + |
| 115 | + /** |
| 116 | + * Base64-decode the given byte array using the RFC 4868 |
| 117 | + * "URL and Filename Safe Alphabet". |
| 118 | + * @param src the encoded byte array (may be {@code null}) |
| 119 | + * @return the original byte array (or {@code null} if the input was {@code null}) |
| 120 | + * @throws IllegalStateException if Base64 encoding between byte arrays is not |
| 121 | + * supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime |
| 122 | + */ |
| 123 | + public static byte[] decodeUrlSafe(byte[] src) { |
| 124 | + assertDelegateAvailable(); |
| 125 | + return delegate.decodeUrlSafe(src); |
| 126 | + } |
| 127 | + |
95 | 128 | /**
|
96 | 129 | * Base64-encode the given byte array to a String.
|
97 | 130 | * @param src the original byte array (may be {@code null})
|
@@ -139,45 +172,110 @@ public static byte[] decodeFromString(String src) {
|
139 | 172 | }
|
140 | 173 | }
|
141 | 174 |
|
| 175 | + /** |
| 176 | + * Base64-encode the given byte array to a String using the RFC 4868 |
| 177 | + * "URL and Filename Safe Alphabet". |
| 178 | + * @param src the original byte array (may be {@code null}) |
| 179 | + * @return the encoded byte array as a UTF-8 String |
| 180 | + * (or {@code null} if the input was {@code null}) |
| 181 | + * @throws IllegalStateException if Base64 encoding between byte arrays is not |
| 182 | + * supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime |
| 183 | + */ |
| 184 | + public static String encodeToUrlSafeString(byte[] src) { |
| 185 | + assertDelegateAvailable(); |
| 186 | + return new String(delegate.encodeUrlSafe(src), DEFAULT_CHARSET); |
| 187 | + } |
| 188 | + |
| 189 | + /** |
| 190 | + * Base64-decode the given byte array from an UTF-8 String using the RFC 4868 |
| 191 | + * "URL and Filename Safe Alphabet". |
| 192 | + * @param src the encoded UTF-8 String (may be {@code null}) |
| 193 | + * @return the original byte array (or {@code null} if the input was {@code null}) |
| 194 | + * @throws IllegalStateException if Base64 encoding between byte arrays is not |
| 195 | + * supported, i.e. neither Java 8 nor Apache Commons Codec is present at runtime |
| 196 | + */ |
| 197 | + public static byte[] decodeFromUrlSafeString(String src) { |
| 198 | + assertDelegateAvailable(); |
| 199 | + return delegate.decodeUrlSafe(src.getBytes(DEFAULT_CHARSET)); |
| 200 | + } |
| 201 | + |
142 | 202 |
|
143 | 203 | interface Base64Delegate {
|
144 | 204 |
|
145 | 205 | byte[] encode(byte[] src);
|
146 | 206 |
|
147 | 207 | byte[] decode(byte[] src);
|
| 208 | + |
| 209 | + byte[] encodeUrlSafe(byte[] src); |
| 210 | + |
| 211 | + byte[] decodeUrlSafe(byte[] src); |
148 | 212 | }
|
149 | 213 |
|
150 | 214 |
|
151 | 215 | @UsesJava8
|
152 | 216 | static class JdkBase64Delegate implements Base64Delegate {
|
153 | 217 |
|
| 218 | + @Override |
154 | 219 | public byte[] encode(byte[] src) {
|
155 | 220 | if (src == null || src.length == 0) {
|
156 | 221 | return src;
|
157 | 222 | }
|
158 | 223 | return Base64.getEncoder().encode(src);
|
159 | 224 | }
|
160 | 225 |
|
| 226 | + @Override |
161 | 227 | public byte[] decode(byte[] src) {
|
162 | 228 | if (src == null || src.length == 0) {
|
163 | 229 | return src;
|
164 | 230 | }
|
165 | 231 | return Base64.getDecoder().decode(src);
|
166 | 232 | }
|
| 233 | + |
| 234 | + @Override |
| 235 | + public byte[] encodeUrlSafe(byte[] src) { |
| 236 | + if (src == null || src.length == 0) { |
| 237 | + return src; |
| 238 | + } |
| 239 | + return Base64.getUrlEncoder().encode(src); |
| 240 | + } |
| 241 | + |
| 242 | + @Override |
| 243 | + public byte[] decodeUrlSafe(byte[] src) { |
| 244 | + if (src == null || src.length == 0) { |
| 245 | + return src; |
| 246 | + } |
| 247 | + return Base64.getUrlDecoder().decode(src); |
| 248 | + } |
| 249 | + |
167 | 250 | }
|
168 | 251 |
|
169 | 252 |
|
170 | 253 | static class CommonsCodecBase64Delegate implements Base64Delegate {
|
171 | 254 |
|
172 | 255 | private final org.apache.commons.codec.binary.Base64 base64 = new org.apache.commons.codec.binary.Base64();
|
173 | 256 |
|
| 257 | + private final org.apache.commons.codec.binary.Base64 base64UrlSafe = new org.apache.commons.codec.binary.Base64(0, null, true); |
| 258 | + |
| 259 | + @Override |
174 | 260 | public byte[] encode(byte[] src) {
|
175 | 261 | return this.base64.encode(src);
|
176 | 262 | }
|
177 | 263 |
|
| 264 | + @Override |
178 | 265 | public byte[] decode(byte[] src) {
|
179 | 266 | return this.base64.decode(src);
|
180 | 267 | }
|
| 268 | + |
| 269 | + @Override |
| 270 | + public byte[] encodeUrlSafe(byte[] src) { |
| 271 | + return this.base64UrlSafe.encode(src); |
| 272 | + } |
| 273 | + |
| 274 | + @Override |
| 275 | + public byte[] decodeUrlSafe(byte[] src) { |
| 276 | + return this.base64UrlSafe.decode(src); |
| 277 | + } |
| 278 | + |
181 | 279 | }
|
182 | 280 |
|
183 | 281 | }
|
0 commit comments