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    
022    import org.apache.commons.codec.DecoderException;
023    import org.apache.commons.codec.EncoderException;
024    import org.apache.commons.codec.CharEncoding;
025    import org.apache.commons.codec.StringDecoder;
026    import org.apache.commons.codec.StringEncoder;
027    import 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     */
048    public 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    }