/
Base64EncoderStream.java
187 lines (171 loc) · 5.61 KB
/
Base64EncoderStream.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
* Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package org.jvnet.staxex;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
// for testing method
//import com.sun.xml.stream.writers.XMLStreamWriterImpl;
/**
* This class implements a BASE64 Encoder. It is implemented as
* a FilterOutputStream, so one can just wrap this class around
* any output stream and write bytes into this filter. The Encoding
* is done as the bytes are written out.
*
* @author John Mani
* @author Bill Shannon
* @author Martin Grebac
*/
public class Base64EncoderStream extends FilterOutputStream {
private byte[] buffer; // cache of bytes that are yet to be encoded
private int bufsize = 0; // size of the cache
private XMLStreamWriter outWriter;
public Base64EncoderStream(OutputStream out) {
super(out);
buffer = new byte[3];
}
/**
* Create a BASE64 encoder that encodes the specified input stream
*/
public Base64EncoderStream(XMLStreamWriter outWriter, OutputStream out) {
super(out);
buffer = new byte[3];
this.outWriter = outWriter;
}
/**
* Encodes <code>len</code> bytes from the specified
* <code>byte</code> array starting at offset <code>off</code> to
* this output stream.
*
* @param b the data.
* @param off the start offset in the data.
* @param len the number of bytes to write.
* @exception IOException if an I/O error occurs.
*/
@Override
public void write(byte[] b, int off, int len) throws IOException {
for (int i = 0; i < len; i++)
write(b[off + i]);
}
/**
* Encodes <code>b.length</code> bytes to this output stream.
* @param b the data to be written.
* @exception IOException if an I/O error occurs.
*/
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
/**
* Encodes the specified <code>byte</code> to this output stream.
* @param c the <code>byte</code>.
* @exception IOException if an I/O error occurs.
*/
@Override
public void write(int c) throws IOException {
buffer[bufsize++] = (byte)c;
if (bufsize == 3) { // Encoding unit = 3 bytes
encode();
bufsize = 0;
}
}
/**
* Flushes this output stream and forces any buffered output bytes
* to be encoded out to the stream.
* @exception IOException if an I/O error occurs.
*/
@Override
public void flush() throws IOException {
if (bufsize > 0) { // If there's unencoded characters in the buffer ..
encode(); // .. encode them
bufsize = 0;
}
out.flush();
try {
outWriter.flush();
} catch (XMLStreamException ex) {
Logger.getLogger(Base64EncoderStream.class.getName()).log(Level.SEVERE, null, ex);
throw new IOException(ex);
}
}
/**
* Forces any buffered output bytes to be encoded out to the stream
* and closes this output stream
*/
@Override
public void close() throws IOException {
flush();
out.close();
}
/** This array maps the characters to their 6 bit values */
private final static char pem_array[] = {
'A','B','C','D','E','F','G','H', // 0
'I','J','K','L','M','N','O','P', // 1
'Q','R','S','T','U','V','W','X', // 2
'Y','Z','a','b','c','d','e','f', // 3
'g','h','i','j','k','l','m','n', // 4
'o','p','q','r','s','t','u','v', // 5
'w','x','y','z','0','1','2','3', // 6
'4','5','6','7','8','9','+','/' // 7
};
private void encode() throws IOException {
byte a, b, c;
char[] buf = new char[4];
if (bufsize == 1) {
a = buffer[0];
b = 0;
c = 0;
buf[0] = pem_array[(a >>> 2) & 0x3F];
buf[1] = pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)];
buf[2] = '='; // pad character
buf[3] = '='; // pad character
} else if (bufsize == 2) {
a = buffer[0];
b = buffer[1];
c = 0;
buf[0] = pem_array[(a >>> 2) & 0x3F];
buf[1] = pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)];
buf[2] = pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)];
buf[3] = '='; // pad character
} else {
a = buffer[0];
b = buffer[1];
c = buffer[2];
buf[0] = pem_array[(a >>> 2) & 0x3F];
buf[1] = pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)];
buf[2] = pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)];
buf[3] = pem_array[c & 0x3F];
}
try {
outWriter.writeCharacters(buf, 0, 4);
} catch (XMLStreamException ex) {
Logger.getLogger(Base64EncoderStream.class.getName()).log(Level.SEVERE, null, ex);
throw new IOException(ex);
}
}
// public static void main(String argv[]) throws Exception {
// FileInputStream infile = new FileInputStream(new File(argv[0]));
// StringWriter sw = new StringWriter();
// XMLStreamWriterImpl wi = new XMLStreamWriterImpl(sw, null);
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Base64EncoderStream encoder = new Base64EncoderStream(wi, baos);
// int c;
//
// while ((c = infile.read()) != -1)
// encoder.write(c);
// encoder.close();
//
// System.out.println("SW: " + sw.toString());
// System.out.println("BAOS: " + baos.toString());
//
// }
}