1 package org.objectweb.celtix.common.util; 2 3 10 11 import java.io.IOException ; 13 import java.io.OutputStream ; 14 import java.io.Writer ; 15 import java.util.logging.Logger ; 16 17 import org.objectweb.celtix.common.i18n.Message; 18 import org.objectweb.celtix.common.logging.LogUtils; 19 20 21 36 public final class Base64Utility { 37 38 private static final Logger LOG = LogUtils.getL7dLogger(Base64Utility.class); 39 40 41 private static final char[] BCS = { 44 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 45 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 46 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 47 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 48 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 49 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', 50 '8', '9', '+', '/' 51 }; 52 53 private static final char PAD = '='; 55 56 private static final int BDTSIZE = 128; 58 59 private static final byte[] BDT = new byte[128]; 61 62 63 private static final int PAD_SIZE0 = 1; 64 private static final int PAD_SIZE4 = 2; 65 private static final int PAD_SIZE8 = 3; 66 67 static { 69 for (int i = 0; i < BDTSIZE; i++) { 70 BDT[i] = Byte.MAX_VALUE; 71 } 72 73 for (int i = 0; i < BCS.length; i++) { 74 BDT[BCS[i]] = (byte)i; 75 } 76 } 77 78 79 private Base64Utility() { 80 } 82 83 102 public static byte[] decodeChunk(char[] id, 103 int o, 104 int l) 105 throws Base64Exception { 106 107 if (((l - o) % 4 != 0) || (l - o) < 4) { 111 return null; 112 } 113 114 char[] ib = new char[4]; 115 int ibcount = 0; 116 117 int octetCount = 3 * (l / 4); 121 122 if (id[l - 1] == PAD) { 126 octetCount -= (id[l - 2] == PAD) ? 2 : 1; 129 } 130 131 byte[] ob = new byte[octetCount]; 132 int obcount = 0; 133 134 for (int i = o; i < o + l && i < id.length; i++) { 135 if (id[i] == PAD 136 || id[i] < BDT.length 137 && BDT[id[i]] != Byte.MAX_VALUE) { 138 139 ib[ibcount++] = id[i]; 140 141 if (ibcount == ib.length) { 144 ibcount = 0; 145 obcount += processEncodeme(ib, ob, obcount); 146 } 147 } 148 } 149 150 return ob; 151 } 152 153 public static byte[] decode(String id) throws Base64Exception { 154 char[] cd = id.toCharArray(); 155 return decodeChunk(cd, 0, cd.length); 156 } 157 158 public static void decode(char[] id, 159 int o, 160 int l, 161 OutputStream ostream) 162 throws Base64Exception { 163 164 try { 165 ostream.write(decodeChunk(id, o, l)); 166 } catch (IOException e) { 167 throw new Base64Exception(new Message("BASE64_RUNTIME_EXCEPTION", LOG), e); 169 } 170 } 171 172 public static void decode(String id, 173 OutputStream ostream) 174 throws Base64Exception { 175 176 try { 177 char[] cd = id.toCharArray(); 178 ostream.write(decodeChunk(cd, 0, cd.length)); 179 } catch (IOException e) { 180 throw new Base64Exception(new Message("BASE64_DECODE_IOEXCEPTION", LOG), e); 181 } 182 } 183 184 public static String encode(byte[] id) { 187 char[] cd = encodeChunk(id, 0, id.length); 188 return new String (cd, 0, cd.length); 189 } 190 191 public static char[] encodeChunk(byte[] id, 194 int o, 195 int l) { 196 if (l <= 0) { 197 return null; 198 } 199 200 char[] out; 201 202 if ((l - o) % 3 == 0) { 206 out = new char[l / 3 * 4]; 207 } else { 208 out = new char[l / 3 * 4 + 4]; 209 } 210 211 int rindex = o; 212 int windex = 0; 213 int rest = l - o; 214 215 while (rest >= 3) { 216 int i = ((id[rindex] & 0xff) << 16) 217 + ((id[rindex + 1] & 0xff) << 8) 218 + (id[rindex + 2] & 0xff); 219 220 out[windex++] = BCS[i >> 18]; 221 out[windex++] = BCS[(i >> 12) & 0x3f]; 222 out[windex++] = BCS[(i >> 6) & 0x3f]; 223 out[windex++] = BCS[i & 0x3f]; 224 rindex += 3; 225 rest -= 3; 226 } 227 228 if (rest == 1) { 229 int i = id[rindex] & 0xff; 230 out[windex++] = BCS[i >> 2]; 231 out[windex++] = BCS[(i << 4) & 0x3f]; 232 out[windex++] = PAD; 233 out[windex++] = PAD; 234 } else if (rest == 2) { 235 int i = ((id[rindex] & 0xff) << 8) + (id[rindex + 1] & 0xff); 236 out[windex++] = BCS[i >> 10]; 237 out[windex++] = BCS[(i >> 4) & 0x3f]; 238 out[windex++] = BCS[(i << 2) & 0x3f]; 239 out[windex++] = PAD; 240 } 241 return out; 242 } 243 244 public static void encodeChunk(byte[] id, 249 int o, 250 int l, 251 OutputStream ostream) throws Base64Exception { 252 try { 253 ostream.write(new String (encodeChunk(id, o, l)).getBytes()); 254 } catch (IOException e) { 255 throw new Base64Exception(new Message("BASE64_ENCODE_IOEXCEPTION", LOG), e); 256 } 257 } 258 259 260 public static void encode(byte[] id, 264 int o, 265 int l, 266 Writer writer) throws Base64Exception { 267 try { 268 writer.write(encodeChunk(id, o, l)); 269 } catch (IOException e) { 270 throw new Base64Exception(new Message("BASE64_ENCODE_WRITER_IOEXCEPTION", LOG), e); 271 } 272 } 273 274 275 277 290 private static int processEncodeme(char[] ib, 291 byte[] ob, 292 int p) 293 throws Base64Exception { 294 295 296 int spad = PAD_SIZE8; 297 if (ib[3] == PAD) { 298 spad = PAD_SIZE4; 299 } 300 if (ib[2] == PAD) { 301 spad = PAD_SIZE0; 302 } 303 304 int b0 = BDT[ib[0]]; 305 int b1 = BDT[ib[1]]; 306 int b2 = BDT[ib[2]]; 307 int b3 = BDT[ib[3]]; 308 309 switch (spad) { 310 case PAD_SIZE0: 311 ob[p] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); 312 return PAD_SIZE0; 313 case PAD_SIZE4: 314 ob[p++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); 315 ob[p] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf); 316 return PAD_SIZE4; 317 case PAD_SIZE8: 318 ob[p++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); 319 ob[p++] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf); 320 ob[p] = (byte)(b2 << 6 & 0xc0 | b3 & 0x3f); 321 return PAD_SIZE8; 322 default: 323 throw new IllegalStateException (); 325 } 326 } 327 328 } 329 | Popular Tags |