001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.codec.net;
019
020 import java.io.UnsupportedEncodingException;
021 import java.nio.charset.Charset;
022
023 import org.apache.commons.codec.Charsets;
024 import org.apache.commons.codec.DecoderException;
025 import org.apache.commons.codec.EncoderException;
026 import org.apache.commons.codec.StringDecoder;
027 import org.apache.commons.codec.StringEncoder;
028 import org.apache.commons.codec.binary.Base64;
029
030 /**
031 * Identical to the Base64 encoding defined by <a href="http://www.ietf.org/rfc/rfc1521.txt">RFC 1521</a>
032 * and allows a character set to be specified.
033 * <p>
034 * <a href="http://www.ietf.org/rfc/rfc1522.txt">RFC 1522</a> describes techniques to allow the encoding of non-ASCII
035 * text in various portions of a RFC 822 [2] message header, in a manner which is unlikely to confuse existing message
036 * handling software.
037 * <p>
038 * This class is immutable and thread-safe.
039 *
040 * @see <a href="http://www.ietf.org/rfc/rfc1522.txt">MIME (Multipurpose Internet Mail Extensions) Part Two: Message
041 * Header Extensions for Non-ASCII Text</a>
042 *
043 * @since 1.3
044 * @version $Id: BCodec.html 889935 2013-12-11 05:05:13Z ggregory $
045 */
046 public class BCodec extends RFC1522Codec implements StringEncoder, StringDecoder {
047 /**
048 * The default charset used for string decoding and encoding.
049 */
050 private final Charset charset;
051
052 /**
053 * Default constructor.
054 */
055 public BCodec() {
056 this(Charsets.UTF_8);
057 }
058
059 /**
060 * Constructor which allows for the selection of a default charset
061 *
062 * @param charset
063 * the default string charset to use.
064 *
065 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
066 * @since 1.7
067 */
068 public BCodec(final Charset charset) {
069 this.charset = charset;
070 }
071
072 /**
073 * Constructor which allows for the selection of a default charset
074 *
075 * @param charsetName
076 * the default charset to use.
077 * @throws java.nio.charset.UnsupportedCharsetException
078 * If the named charset is unavailable
079 * @since 1.7 throws UnsupportedCharsetException if the named charset is unavailable
080 * @see <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
081 */
082 public BCodec(final String charsetName) {
083 this(Charset.forName(charsetName));
084 }
085
086 @Override
087 protected String getEncoding() {
088 return "B";
089 }
090
091 @Override
092 protected byte[] doEncoding(final byte[] bytes) {
093 if (bytes == null) {
094 return null;
095 }
096 return Base64.encodeBase64(bytes);
097 }
098
099 @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 }