| /* |
| * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| * |
| * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC. |
| */ |
| |
| package com.sun.xml.internal.fastinfoset.algorithm; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmException; |
| import com.sun.xml.internal.fastinfoset.CommonResourceBundle; |
| |
| public class BASE64EncodingAlgorithm extends BuiltInEncodingAlgorithm { |
| |
| /* package */ static final char encodeBase64[] = { |
| 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', |
| 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
| 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', |
| 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', |
| '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' |
| }; |
| |
| /* package */ static final int decodeBase64[] = { |
| /*'+'*/ 62, |
| -1, -1, -1, |
| /*'/'*/ 63, |
| /*'0'*/ 52, |
| /*'1'*/ 53, |
| /*'2'*/ 54, |
| /*'3'*/ 55, |
| /*'4'*/ 56, |
| /*'5'*/ 57, |
| /*'6'*/ 58, |
| /*'7'*/ 59, |
| /*'8'*/ 60, |
| /*'9'*/ 61, |
| -1, -1, -1, -1, -1, -1, -1, |
| /*'A'*/ 0, |
| /*'B'*/ 1, |
| /*'C'*/ 2, |
| /*'D'*/ 3, |
| /*'E'*/ 4, |
| /*'F'*/ 5, |
| /*'G'*/ 6, |
| /*'H'*/ 7, |
| /*'I'*/ 8, |
| /*'J'*/ 9, |
| /*'K'*/ 10, |
| /*'L'*/ 11, |
| /*'M'*/ 12, |
| /*'N'*/ 13, |
| /*'O'*/ 14, |
| /*'P'*/ 15, |
| /*'Q'*/ 16, |
| /*'R'*/ 17, |
| /*'S'*/ 18, |
| /*'T'*/ 19, |
| /*'U'*/ 20, |
| /*'V'*/ 21, |
| /*'W'*/ 22, |
| /*'X'*/ 23, |
| /*'Y'*/ 24, |
| /*'Z'*/ 25, |
| -1, -1, -1, -1, -1, -1, |
| /*'a'*/ 26, |
| /*'b'*/ 27, |
| /*'c'*/ 28, |
| /*'d'*/ 29, |
| /*'e'*/ 30, |
| /*'f'*/ 31, |
| /*'g'*/ 32, |
| /*'h'*/ 33, |
| /*'i'*/ 34, |
| /*'j'*/ 35, |
| /*'k'*/ 36, |
| /*'l'*/ 37, |
| /*'m'*/ 38, |
| /*'n'*/ 39, |
| /*'o'*/ 40, |
| /*'p'*/ 41, |
| /*'q'*/ 42, |
| /*'r'*/ 43, |
| /*'s'*/ 44, |
| /*'t'*/ 45, |
| /*'u'*/ 46, |
| /*'v'*/ 47, |
| /*'w'*/ 48, |
| /*'x'*/ 49, |
| /*'y'*/ 50, |
| /*'z'*/ 51 |
| }; |
| |
| public final Object decodeFromBytes(byte[] b, int start, int length) throws EncodingAlgorithmException { |
| final byte[] data = new byte[length]; |
| System.arraycopy(b, start, data, 0, length); |
| return data; |
| } |
| |
| public final Object decodeFromInputStream(InputStream s) throws IOException { |
| throw new UnsupportedOperationException(CommonResourceBundle.getInstance().getString("message.notImplemented")); |
| } |
| |
| |
| public void encodeToOutputStream(Object data, OutputStream s) throws IOException { |
| if (!(data instanceof byte[])) { |
| throw new IllegalArgumentException(CommonResourceBundle.getInstance().getString("message.dataNotByteArray")); |
| } |
| |
| s.write((byte[])data); |
| } |
| |
| public final Object convertFromCharacters(char[] ch, int start, int length) { |
| if (length == 0) { |
| return new byte[0]; |
| } |
| |
| StringBuilder encodedValue = removeWhitespace(ch, start, length); |
| int encodedLength = encodedValue.length(); |
| if (encodedLength == 0) { |
| return new byte[0]; |
| } |
| |
| int blockCount = encodedLength / 4; |
| int partialBlockLength = 3; |
| |
| if (encodedValue.charAt(encodedLength - 1) == '=') { |
| --partialBlockLength; |
| if (encodedValue.charAt(encodedLength - 2) == '=') { |
| --partialBlockLength; |
| } |
| } |
| |
| int valueLength = (blockCount - 1) * 3 + partialBlockLength; |
| byte[] value = new byte[valueLength]; |
| |
| int idx = 0; |
| int encodedIdx = 0; |
| for (int i = 0; i < blockCount; ++i) { |
| int x1 = decodeBase64[encodedValue.charAt(encodedIdx++) - '+']; |
| int x2 = decodeBase64[encodedValue.charAt(encodedIdx++) - '+']; |
| int x3 = decodeBase64[encodedValue.charAt(encodedIdx++) - '+']; |
| int x4 = decodeBase64[encodedValue.charAt(encodedIdx++) - '+']; |
| |
| value[idx++] = (byte) ((x1 << 2) | (x2 >> 4)); |
| if (idx < valueLength) { |
| value[idx++] = (byte) (((x2 & 0x0f) << 4) | (x3 >> 2)); |
| } |
| if (idx < valueLength) { |
| value[idx++] = (byte) (((x3 & 0x03) << 6) | x4); |
| } |
| } |
| |
| return value; |
| } |
| |
| public final void convertToCharacters(Object data, StringBuffer s) { |
| if (data == null) { |
| return; |
| } |
| final byte[] value = (byte[]) data; |
| |
| convertToCharacters(value, 0, value.length, s); |
| } |
| |
| public final int getPrimtiveLengthFromOctetLength(int octetLength) throws EncodingAlgorithmException { |
| return octetLength; |
| } |
| |
| public int getOctetLengthFromPrimitiveLength(int primitiveLength) { |
| return primitiveLength; |
| } |
| |
| public final void encodeToBytes(Object array, int astart, int alength, byte[] b, int start) { |
| System.arraycopy((byte[])array, astart, b, start, alength); |
| } |
| |
| public final void convertToCharacters(byte[] data, int offset, int length, StringBuffer s) { |
| if (data == null) { |
| return; |
| } |
| final byte[] value = data; |
| if (length == 0) { |
| return; |
| } |
| |
| final int partialBlockLength = length % 3; |
| final int blockCount = (partialBlockLength != 0) ? |
| length / 3 + 1 : |
| length / 3; |
| |
| final int encodedLength = blockCount * 4; |
| final int originalBufferSize = s.length(); |
| s.ensureCapacity(encodedLength + originalBufferSize); |
| |
| int idx = offset; |
| int lastIdx = offset + length; |
| for (int i = 0; i < blockCount; ++i) { |
| int b1 = value[idx++] & 0xFF; |
| int b2 = (idx < lastIdx) ? value[idx++] & 0xFF : 0; |
| int b3 = (idx < lastIdx) ? value[idx++] & 0xFF : 0; |
| |
| s.append(encodeBase64[b1 >> 2]); |
| |
| s.append(encodeBase64[((b1 & 0x03) << 4) | (b2 >> 4)]); |
| |
| s.append(encodeBase64[((b2 & 0x0f) << 2) | (b3 >> 6)]); |
| |
| s.append(encodeBase64[b3 & 0x3f]); |
| } |
| |
| switch (partialBlockLength) { |
| case 1 : |
| s.setCharAt(originalBufferSize + encodedLength - 1, '='); |
| s.setCharAt(originalBufferSize + encodedLength - 2, '='); |
| break; |
| case 2 : |
| s.setCharAt(originalBufferSize + encodedLength - 1, '='); |
| break; |
| } |
| } |
| } |