1
15 package com.amazonaws.util;
16
17 import javax.xml.bind.DatatypeConverter;
18 import javax.xml.bind.JAXBContext;
19
20 import com.amazonaws.log.InternalLogApi;
21 import com.amazonaws.log.InternalLogFactory;
22
23 import java.util.HashMap;
24 import java.util.Map;
25
26
33 public enum Base64 {
34 ;
35 private static final InternalLogApi LOG = InternalLogFactory.getLog(Base64.class);
36 private static final Base64Codec codec = new Base64Codec();
37 private static final boolean isJaxbAvailable;
38
39 static {
40 boolean available;
41 try {
42 Class.forName("javax.xml.bind.DatatypeConverter");
43 available = true;
44 } catch (Exception e) {
45 available = false;
46 }
47 if (available) {
48 Map<String, String> inconsistentJaxbImpls = new HashMap<String, String>();
49 inconsistentJaxbImpls.put("org.apache.ws.jaxme.impl.JAXBContextImpl", "Apache JaxMe");
50
51 try {
52 String className = JAXBContext.newInstance().getClass().getName();
53 if (inconsistentJaxbImpls.containsKey(className)) {
54 LOG.warn("A JAXB implementation known to produce base64 encodings that are " +
55 "inconsistent with the reference implementation has been detected. The " +
56 "results of the encodeAsString() method may be incorrect. Implementation: " +
57 inconsistentJaxbImpls.get(className));
58 }
59 } catch (UnsupportedOperationException ignored) {
60 available = false;
61 } catch (Exception ignored) {
62
63 } catch (NoClassDefFoundError error){
64
65 }
66 } else {
67 LOG.warn("JAXB is unavailable. Will fallback to SDK implementation which may be less performant." +
68 "If you are using Java 9+, you will need to include javax.xml.bind:jaxb-api as a dependency.");
69 }
70
71 isJaxbAvailable = available;
72 }
73
74
77 public static String encodeAsString(byte... bytes) {
78 if (bytes == null) {
79 return null;
80 }
81 if (isJaxbAvailable) {
82 try {
83 return DatatypeConverter.printBase64Binary(bytes);
84 } catch (NullPointerException ex) {
85
86
87
88
89 LOG.debug("Recovering from JAXB bug: https:, ex);
90 }
91 }
92
93 return bytes.length == 0 ? "" : CodecUtils.toStringDirect(codec.encode(bytes));
94 }
95
96
99 public static byte[] encode(byte[] bytes) {
100 return bytes == null || bytes.length == 0 ? bytes : codec.encode(bytes);
101 }
102
103
107 public static byte[] decode(String b64) {
108 if (b64 == null) {
109 return null;
110 }
111 if (b64.length() == 0) {
112 return new byte[0];
113 }
114 byte[] buf = new byte[b64.length()];
115 int len = CodecUtils.sanitize(b64, buf);
116 return codec.decode(buf, len);
117 }
118
119
122 public static byte[] decode(byte[] b64) {
123 return b64 == null || b64.length == 0 ? b64 : codec.decode(b64, b64.length);
124 }
125 }
126
127