1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.codec.net;
19
20 import java.io.UnsupportedEncodingException;
21 import java.nio.charset.Charset;
22
23 import org.apache.commons.codec.Charsets;
24 import org.apache.commons.codec.DecoderException;
25 import org.apache.commons.codec.EncoderException;
26 import org.apache.commons.codec.StringDecoder;
27 import org.apache.commons.codec.StringEncoder;
28 import org.apache.commons.codec.binary.Base64;
29
30 /**
31 * Identical to the Base64 encoding defined by <a href="http://www.ietf.org/rfc/rfc1521.txt">RFC 1521</a>
32 * and allows a character set to be specified.
33 * <p>
34 * <a href="http://www.ietf.org/rfc/rfc1522.txt">RFC 1522</a> describes techniques to allow the encoding of non-ASCII
35 * text in various portions of a RFC 822 [2] message header, in a manner which is unlikely to confuse existing message
36 * handling software.
37 * <p>
38 * This class is immutable and thread-safe.
39 *
40 * @see <a href="http://www.ietf.org/rfc/rfc1522.txt">MIME (Multipurpose Internet Mail Extensions) Part Two: Message
41 * Header Extensions for Non-ASCII Text</a>
42 *
43 * @since 1.3
44 * @version $Id: BCodec.html 889935 2013-12-11 05:05:13Z ggregory $
45 */
46 public class BCodec extends RFC1522Codec implements StringEncoder, StringDecoder {
47 /**
48 * The default charset used for string decoding and encoding.
49 */
50 private final Charset charset;
51
52 /**
53 * Default constructor.
54 */
55 public BCodec() {
56 this(Charsets.UTF_8);
57 }
58
59 /**
60 * Constructor which allows for the selection of a default charset
61 *
62 * @param charset
63 * the default string charset to use.
64 *
65 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
66 * @since 1.7
67 */
68 public BCodec(final Charset charset) {
69 this.charset = charset;
70 }
71
72 /**
73 * Constructor which allows for the selection of a default charset
74 *
75 * @param charsetName
76 * the default charset to use.
77 * @throws java.nio.charset.UnsupportedCharsetException
78 * If the named charset is unavailable
79 * @since 1.7 throws UnsupportedCharsetException if the named charset is unavailable
80 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
81 */
82 public BCodec(final String charsetName) {
83 this(Charset.forName(charsetName));
84 }
85
86 @Override
87 protected String getEncoding() {
88 return "B";
89 }
90
91 @Override
92 protected byte[] doEncoding(final byte[] bytes) {
93 if (bytes == null) {
94 return null;
95 }
96 return Base64.encodeBase64(bytes);
97 }
98
99 @Override
100 protected byte[] doDecoding(final byte[] bytes) {
101 if (bytes == null) {
102 return null;
103 }
104 return Base64.decodeBase64(bytes);
105 }
106
107 /**
108 * Encodes a string into its Base64 form using the specified charset. Unsafe characters are escaped.
109 *
110 * @param value
111 * string to convert to Base64 form
112 * @param charset
113 * the charset for <code>value</code>
114 * @return Base64 string
115 * @throws EncoderException
116 * thrown if a failure condition is encountered during the encoding process.
117 * @since 1.7
118 */
119 public String encode(final String value, final Charset charset) throws EncoderException {
120 if (value == null) {
121 return null;
122 }
123 return encodeText(value, charset);
124 }
125
126 /**
127 * Encodes a string into its Base64 form using the specified charset. Unsafe characters are escaped.
128 *
129 * @param value
130 * string to convert to Base64 form
131 * @param charset
132 * the charset for <code>value</code>
133 * @return Base64 string
134 * @throws EncoderException
135 * thrown if a failure condition is encountered during the encoding process.
136 */
137 public String encode(final String value, final String charset) throws EncoderException {
138 if (value == null) {
139 return null;
140 }
141 try {
142 return this.encodeText(value, charset);
143 } catch (final UnsupportedEncodingException e) {
144 throw new EncoderException(e.getMessage(), e);
145 }
146 }
147
148 /**
149 * Encodes a string into its Base64 form using the default charset. Unsafe characters are escaped.
150 *
151 * @param value
152 * string to convert to Base64 form
153 * @return Base64 string
154 * @throws EncoderException
155 * thrown if a failure condition is encountered during the encoding process.
156 */
157 @Override
158 public String encode(final String value) throws EncoderException {
159 if (value == null) {
160 return null;
161 }
162 return encode(value, this.getCharset());
163 }
164
165 /**
166 * Decodes a Base64 string into its original form. Escaped characters are converted back to their original
167 * representation.
168 *
169 * @param value
170 * Base64 string to convert into its original form
171 * @return original string
172 * @throws DecoderException
173 * A decoder exception is thrown if a failure condition is encountered during the decode process.
174 */
175 @Override
176 public String decode(final String value) throws DecoderException {
177 if (value == null) {
178 return null;
179 }
180 try {
181 return this.decodeText(value);
182 } catch (final UnsupportedEncodingException e) {
183 throw new DecoderException(e.getMessage(), e);
184 }
185 }
186
187 /**
188 * Encodes an object into its Base64 form using the default charset. Unsafe characters are escaped.
189 *
190 * @param value
191 * object to convert to Base64 form
192 * @return Base64 object
193 * @throws EncoderException
194 * thrown if a failure condition is encountered during the encoding process.
195 */
196 @Override
197 public Object encode(final Object value) throws EncoderException {
198 if (value == null) {
199 return null;
200 } else if (value instanceof String) {
201 return encode((String) value);
202 } else {
203 throw new EncoderException("Objects of type " +
204 value.getClass().getName() +
205 " cannot be encoded using BCodec");
206 }
207 }
208
209 /**
210 * Decodes a Base64 object into its original form. Escaped characters are converted back to their original
211 * representation.
212 *
213 * @param value
214 * Base64 object to convert into its original form
215 * @return original object
216 * @throws DecoderException
217 * Thrown if the argument is not a <code>String</code>. Thrown if a failure condition is encountered
218 * during the decode process.
219 */
220 @Override
221 public Object decode(final Object value) throws DecoderException {
222 if (value == null) {
223 return null;
224 } else if (value instanceof String) {
225 return decode((String) value);
226 } else {
227 throw new DecoderException("Objects of type " +
228 value.getClass().getName() +
229 " cannot be decoded using BCodec");
230 }
231 }
232
233 /**
234 * Gets the default charset name used for string decoding and encoding.
235 *
236 * @return the default charset name
237 * @since 1.7
238 */
239 public Charset getCharset() {
240 return this.charset;
241 }
242
243 /**
244 * Gets the default charset name used for string decoding and encoding.
245 *
246 * @return the default charset name
247 */
248 public String getDefaultCharset() {
249 return this.charset.name();
250 }
251 }