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
018package org.apache.commons.codec.net;
019
020import java.io.UnsupportedEncodingException;
021
022import org.apache.commons.codec.DecoderException;
023import org.apache.commons.codec.EncoderException;
024import org.apache.commons.codec.CharEncoding;
025import org.apache.commons.codec.StringDecoder;
026import org.apache.commons.codec.StringEncoder;
027import org.apache.commons.codec.binary.Base64;
028
029/**
030 * <p>
031 * Identical to the Base64 encoding defined by <a href="http://www.ietf.org/rfc/rfc1521.txt">RFC
032 * 1521</a> and allows a character set to be specified.
033 * </p>
034 * 
035 * <p>
036 * <a href="http://www.ietf.org/rfc/rfc1522.txt">RFC 1522</a> describes techniques to allow the encoding of non-ASCII
037 * text in various portions of a RFC 822 [2] message header, in a manner which is unlikely to confuse existing message
038 * handling software.
039 * </p>
040 * 
041 * @see <a href="http://www.ietf.org/rfc/rfc1522.txt">MIME (Multipurpose Internet Mail Extensions) Part Two: Message
042 *          Header Extensions for Non-ASCII Text</a>
043 * 
044 * @author Apache Software Foundation
045 * @since 1.3
046 * @version $Id: BCodec.java 797857 2009-07-25 23:43:33Z ggregory $
047 */
048public class BCodec extends RFC1522Codec implements StringEncoder, StringDecoder {
049    /**
050     * The default charset used for string decoding and encoding.
051     */
052    private final String charset;
053
054    /**
055     * Default constructor.
056     */
057    public BCodec() {
058        this(CharEncoding.UTF_8);
059    }
060
061    /**
062     * Constructor which allows for the selection of a default charset
063     * 
064     * @param charset
065     *                  the default string charset to use.
066     * 
067     * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
068     */
069    public BCodec(final String charset) {
070        super();
071        this.charset = charset;
072    }
073
074    protected String getEncoding() {
075        return "B";
076    }
077
078    protected byte[] doEncoding(byte[] bytes) {
079        if (bytes == null) {
080            return null;
081        }
082        return Base64.encodeBase64(bytes);
083    }
084
085    protected byte[] doDecoding(byte[] bytes) {
086        if (bytes == null) {
087            return null;
088        }
089        return Base64.decodeBase64(bytes);
090    }
091
092    /**
093     * Encodes a string into its Base64 form using the specified charset. Unsafe characters are escaped.
094     * 
095     * @param value
096     *                  string to convert to Base64 form
097     * @param charset
098     *                  the charset for <code>value</code>
099     * @return Base64 string
100     * 
101     * @throws EncoderException
102     *                  thrown if a failure condition is encountered during the encoding process.
103     */
104    public String encode(final String value, final String charset) throws EncoderException {
105        if (value == null) {
106            return null;
107        }
108        try {
109            return encodeText(value, charset);
110        } catch (UnsupportedEncodingException e) {
111            throw new EncoderException(e.getMessage(), e);
112        }
113    }
114
115    /**
116     * Encodes a string into its Base64 form using the default charset. Unsafe characters are escaped.
117     * 
118     * @param value
119     *                  string to convert to Base64 form
120     * @return Base64 string
121     * 
122     * @throws EncoderException
123     *                  thrown if a failure condition is encountered during the encoding process.
124     */
125    public String encode(String value) throws EncoderException {
126        if (value == null) {
127            return null;
128        }
129        return encode(value, getDefaultCharset());
130    }
131
132    /**
133     * Decodes a Base64 string into its original form. Escaped characters are converted back to their original
134     * representation.
135     * 
136     * @param value
137     *            Base64 string to convert into its original form
138     * @return original string
139     * @throws DecoderException
140     *             A decoder exception is thrown if a failure condition is encountered during the decode process.
141     */
142    public String decode(String value) throws DecoderException {
143        if (value == null) {
144            return null;
145        }
146        try {
147            return decodeText(value);
148        } catch (UnsupportedEncodingException e) {
149            throw new DecoderException(e.getMessage(), e);
150        }
151    }
152
153    /**
154     * Encodes an object into its Base64 form using the default charset. Unsafe characters are escaped.
155     * 
156     * @param value
157     *                  object to convert to Base64 form
158     * @return Base64 object
159     * 
160     * @throws EncoderException
161     *                  thrown if a failure condition is encountered during the encoding process.
162     */
163    public Object encode(Object value) throws EncoderException {
164        if (value == null) {
165            return null;
166        } else if (value instanceof String) {
167            return encode((String) value);
168        } else {
169            throw new EncoderException("Objects of type " +
170                  value.getClass().getName() +
171                  " cannot be encoded using BCodec");
172        }
173    }
174
175    /**
176     * Decodes a Base64 object into its original form. Escaped characters are converted back to their original
177     * representation.
178     * 
179     * @param value
180     *                  Base64 object to convert into its original form
181     * 
182     * @return original object
183     * 
184     * @throws DecoderException
185     *                  Thrown if the argument is not a <code>String</code>. Thrown if a failure condition is
186     *                  encountered during the decode process.
187     */
188    public Object decode(Object value) throws DecoderException {
189        if (value == null) {
190            return null;
191        } else if (value instanceof String) {
192            return decode((String) value);
193        } else {
194            throw new DecoderException("Objects of type " +
195                  value.getClass().getName() +
196                  " cannot be decoded using BCodec");
197        }
198    }
199
200    /**
201     * The default charset used for string decoding and encoding.
202     * 
203     * @return the default string charset.
204     */
205    public String getDefaultCharset() {
206        return this.charset;
207    }
208}