1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.castor.core.util;
15
16
17
18
19
20
21
22
23
24
25 public final class Base64Encoder {
26
27 private static final int OCTET_3 = 3;
28
29
30 private static final int OCTET_1_MASK = 0x00FFFF;
31
32
33 private static final int OCTET_2_MASK = 0xFF00FF;
34
35
36 private static final int OCTET_3_MASK = 0xFFFF00;
37
38
39 private static final int OCTET_MASK = 0xFF;
40
41
42 private static final int SHIFT_1_OCTET = 8;
43
44
45 private static final int SHIFT_2_OCTET = 16;
46
47
48 private static final int SEXTET_MASK = 0x3F;
49
50
51 private static final int SHIFT_1_SEXTET = 6;
52
53
54 private static final int SHIFT_2_SEXTET = 12;
55
56
57 private static final int SHIFT_3_SEXTET = 18;
58
59
60 private static final char[] MAP = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
61 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
62 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
63 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
64 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
65 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
66 'w', 'x', 'y', 'z', '0', '1', '2', '3',
67 '4', '5', '6', '7', '8', '9', '+', '/',
68 };
69
70
71 private int _buffer = 0;
72
73
74 private int _octets = 0;
75
76
77 private StringBuffer _stream = new StringBuffer();
78
79
80
81
82
83
84
85 public static char[] encode(final byte[] bytes) {
86 Base64Encoder enc = new Base64Encoder();
87 enc.translate(bytes);
88 return enc.getCharArray();
89 }
90
91
92
93
94 public Base64Encoder() {}
95
96
97
98
99
100 public void reset() {
101 _buffer = 0;
102 _octets = 0;
103 _stream = new StringBuffer();
104 }
105
106
107
108
109
110
111
112
113 public void translate(final byte[] bytes) {
114 for (int i = 0; i < bytes.length; i++) {
115 byte b = bytes[i];
116
117 if (_octets == 0) {
118 _buffer = (_buffer & OCTET_1_MASK) | ((b & OCTET_MASK) << SHIFT_2_OCTET);
119 } else if (_octets == 1) {
120 _buffer = (_buffer & OCTET_2_MASK) | ((b & OCTET_MASK) << SHIFT_1_OCTET);
121 } else {
122 _buffer = (_buffer & OCTET_3_MASK) | (b & OCTET_MASK);
123 }
124
125 if ((++_octets) == OCTET_3) {
126 encode();
127 }
128 }
129 }
130
131
132
133
134 private void encode() {
135 _stream.append(MAP[SEXTET_MASK & (_buffer >> SHIFT_3_SEXTET)]);
136 _stream.append(MAP[SEXTET_MASK & (_buffer >> SHIFT_2_SEXTET)]);
137 _stream.append(MAP[SEXTET_MASK & (_buffer >> SHIFT_1_SEXTET)]);
138 _stream.append(MAP[SEXTET_MASK & _buffer]);
139 _buffer = 0;
140 _octets = 0;
141 }
142
143
144
145
146 private void encodeWithPadding() {
147 _stream.append(MAP[SEXTET_MASK & (_buffer >> SHIFT_3_SEXTET)]);
148 _stream.append(MAP[SEXTET_MASK & (_buffer >> SHIFT_2_SEXTET)]);
149 if (_octets <= 1) {
150 _stream.append('=');
151 } else {
152 _stream.append(MAP[SEXTET_MASK & (_buffer >> SHIFT_1_SEXTET)]);
153 }
154 if (_octets <= 2) {
155 _stream.append('=');
156 } else {
157 _stream.append(MAP[SEXTET_MASK & _buffer]);
158 }
159 _buffer = 0;
160 _octets = 0;
161 }
162
163
164
165
166
167
168 public char[] getCharArray() {
169 if (_octets > 0) {
170 encodeWithPadding();
171 }
172 char[] chars = new char[_stream.length()];
173 if (_stream.length() > 0) {
174 _stream.getChars(0, _stream.length(), chars, 0);
175 }
176 return chars;
177 }
178 }