All Downloads are FREE. Search and download functionalities are using the official Maven repository.

panda.codec.net.RFC1522Codec Maven / Gradle / Ivy

package panda.codec.net;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

import panda.codec.DecoderException;
import panda.codec.EncoderException;
import panda.lang.Strings;

/**
 * Implements methods common to all codecs defined in RFC 1522.
 * 

* RFC 1522 describes techniques to allow the * encoding of non-ASCII text in various portions of a RFC 822 [2] message header, in a manner which * is unlikely to confuse existing message handling software. *

* This class is immutable and thread-safe. * * @see MIME (Multipurpose Internet Mail Extensions) * Part Two: Message Header Extensions for Non-ASCII Text */ abstract class RFC1522Codec { /** Separator. */ protected static final char SEP = '?'; /** Prefix. */ protected static final String POSTFIX = "?="; /** Postfix. */ protected static final String PREFIX = "=?"; /** * Applies an RFC 1522 compliant encoding scheme to the given string of text with the given * charset. *

* This method constructs the "encoded-word" header common to all the RFC 1522 codecs and then * invokes {@link #doEncoding(byte [])} method of a concrete class to perform the specific * encoding. * * @param text a string to encode * @param charset a charset to be used * @return RFC 1522 compliant "encoded-word" * @throws EncoderException thrown if there is an error condition during the Encoding process. * @see Standard * charsets */ protected String encodeText(final String text, final Charset charset) throws EncoderException { if (text == null) { return null; } final StringBuilder buffer = new StringBuilder(); buffer.append(PREFIX); buffer.append(charset); buffer.append(SEP); buffer.append(this.getEncoding()); buffer.append(SEP); final byte[] rawData = this.doEncoding(text.getBytes(charset)); buffer.append(Strings.newStringUsAscii(rawData)); buffer.append(POSTFIX); return buffer.toString(); } /** * Applies an RFC 1522 compliant encoding scheme to the given string of text with the given * charset. *

* This method constructs the "encoded-word" header common to all the RFC 1522 codecs and then * invokes {@link #doEncoding(byte [])} method of a concrete class to perform the specific * encoding. * * @param text a string to encode * @param charsetName the charset to use * @return RFC 1522 compliant "encoded-word" * @throws EncoderException thrown if there is an error condition during the Encoding process. * @throws UnsupportedEncodingException if charset is not available * @see Standard * charsets */ protected String encodeText(final String text, final String charsetName) throws EncoderException, UnsupportedEncodingException { if (text == null) { return null; } return this.encodeText(text, Charset.forName(charsetName)); } /** * Applies an RFC 1522 compliant decoding scheme to the given string of text. *

* This method processes the "encoded-word" header common to all the RFC 1522 codecs and then * invokes {@link #doEncoding(byte [])} method of a concrete class to perform the specific * decoding. * * @param text a string to decode * @return A new decoded String or null if the input is null. * @throws DecoderException thrown if there is an error condition during the decoding process. * @throws UnsupportedEncodingException thrown if charset specified in the "encoded-word" header * is not supported */ protected String decodeText(final String text) throws DecoderException, UnsupportedEncodingException { if (text == null) { return null; } if (!text.startsWith(PREFIX) || !text.endsWith(POSTFIX)) { throw new DecoderException("RFC 1522 violation: malformed encoded content"); } final int terminator = text.length() - 2; int from = 2; int to = text.indexOf(SEP, from); if (to == terminator) { throw new DecoderException("RFC 1522 violation: charset token not found"); } final String charset = text.substring(from, to); if (charset.equals("")) { throw new DecoderException("RFC 1522 violation: charset not specified"); } from = to + 1; to = text.indexOf(SEP, from); if (to == terminator) { throw new DecoderException("RFC 1522 violation: encoding token not found"); } final String encoding = text.substring(from, to); if (!getEncoding().equalsIgnoreCase(encoding)) { throw new DecoderException("This codec cannot decode " + encoding + " encoded content"); } from = to + 1; to = text.indexOf(SEP, from); byte[] data = Strings.getBytesUsAscii(text.substring(from, to)); data = doDecoding(data); return new String(data, charset); } /** * Returns the codec name (referred to as encoding in the RFC 1522). * * @return name of the codec */ protected abstract String getEncoding(); /** * Encodes an array of bytes using the defined encoding scheme. * * @param bytes Data to be encoded * @return A byte array containing the encoded data * @throws EncoderException thrown if the Encoder encounters a failure condition during the * encoding process. */ protected abstract byte[] doEncoding(byte[] bytes) throws EncoderException; /** * Decodes an array of bytes using the defined encoding scheme. * * @param bytes Data to be decoded * @return a byte array that contains decoded data * @throws DecoderException A decoder exception is thrown if a Decoder encounters a failure * condition during the decode process. */ protected abstract byte[] doDecoding(byte[] bytes) throws DecoderException; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy