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

ee.jakarta.tck.ws.rs.lib.util.CharacterDecoder Maven / Gradle / Ivy

/*
 * Copyright (c) 1995, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package ee.jakarta.tck.ws.rs.lib.util;

import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * This class defines the decoding half of character encoders. A character
 * decoder is an algorithim for transforming 8 bit binary data that has been
 * encoded into text by a character encoder, back into original binary form.
 *
 * The character encoders, in general, have been structured around a central
 * theme that binary data can be encoded into text that has the form:
 *
 * 
 *      [Buffer Prefix]
 *      [Line Prefix][encoded data atoms][Line Suffix]
 *      [Buffer Suffix]
 * 
* * Of course in the simplest encoding schemes, the buffer has no distinct prefix * of suffix, however all have some fixed relationship between the text in an * 'atom' and the binary data itself. * * In the CharacterEncoder and CharacterDecoder classes, one complete chunk of * data is referred to as a buffer. Encoded buffers are all text, and * decoded buffers (sometimes just referred to as buffers) are binary octets. * * To create a custom decoder, you must, at a minimum, overide three abstract * methods in this class. *
*
bytesPerAtom which tells the decoder how many bytes to expect from * decodeAtom *
decodeAtom which decodes the bytes sent to it as text. *
bytesPerLine which tells the encoder the maximum number of bytes per * line. *
* * In general, the character decoders return error in the form of a * CEFormatException. The syntax of the detail string is * *
 *      DecoderClassName: Error message.
 * 
* * Several useful decoders have already been written and are referenced in the * See Also list below. * * @author Chuck McManis * @see CEFormatException * @see CharacterEncoder * @see UCDecoder * @see UUDecoder * @see BASE64Decoder */ public abstract class CharacterDecoder { /** Return the number of bytes per atom of decoding */ abstract protected int bytesPerAtom(); /** Return the maximum number of bytes that can be encoded per line */ abstract protected int bytesPerLine(); /** decode the beginning of the buffer, by default this is a NOP. */ protected void decodeBufferPrefix(PushbackInputStream aStream, OutputStream bStream) throws IOException { } /** decode the buffer suffix, again by default it is a NOP. */ protected void decodeBufferSuffix(PushbackInputStream aStream, OutputStream bStream) throws IOException { } /** * This method should return, if it knows, the number of bytes that will be * decoded. Many formats such as uuencoding provide this information. By * default we return the maximum bytes that could have been encoded on the * line. */ protected int decodeLinePrefix(PushbackInputStream aStream, OutputStream bStream) throws IOException { return (bytesPerLine()); } /** * This method post processes the line, if there are error detection or * correction codes in a line, they are generally processed by this method. * The simplest version of this method looks for the (newline) character. */ protected void decodeLineSuffix(PushbackInputStream aStream, OutputStream bStream) throws IOException { } /** * This method does an actual decode. It takes the decoded bytes and writes * them to the OutputStream. The integer l tells the method how many * bytes are required. This is always <= bytesPerAtom(). */ protected void decodeAtom(PushbackInputStream aStream, OutputStream bStream, int l) throws IOException { throw new CEStreamExhausted(); } /** * This method works around the bizarre semantics of BufferedInputStream's * read method. */ protected int readFully(InputStream in, byte buffer[], int offset, int len) throws java.io.IOException { for (int i = 0; i < len; i++) { int q = in.read(); if (q == -1) return ((i == 0) ? -1 : i); buffer[i + offset] = (byte) q; } return len; } /** * Decode the text from the InputStream and write the decoded octets to the * OutputStream. This method runs until the stream is exhausted. * * @exception CEFormatException * An error has occured while decoding * @exception CEStreamExhausted * The input stream is unexpectedly out of data */ public void decodeBuffer(InputStream aStream, OutputStream bStream) throws IOException { int i; int totalBytes = 0; PushbackInputStream ps = new PushbackInputStream(aStream); decodeBufferPrefix(ps, bStream); while (true) { int length; try { length = decodeLinePrefix(ps, bStream); for (i = 0; (i + bytesPerAtom()) < length; i += bytesPerAtom()) { decodeAtom(ps, bStream, bytesPerAtom()); totalBytes += bytesPerAtom(); } if ((i + bytesPerAtom()) == length) { decodeAtom(ps, bStream, bytesPerAtom()); totalBytes += bytesPerAtom(); } else { decodeAtom(ps, bStream, length - i); totalBytes += (length - i); } decodeLineSuffix(ps, bStream); } catch (CEStreamExhausted e) { break; } } decodeBufferSuffix(ps, bStream); } /** * Alternate decode interface that takes a String containing the encoded * buffer and returns a byte array containing the data. * * @exception CEFormatException * An error has occured while decoding */ public byte decodeBuffer(String inputString)[] throws IOException { byte inputBuffer[] = new byte[inputString.length()]; ByteArrayInputStream inStream; ByteArrayOutputStream outStream; inputString.getBytes(0, inputString.length(), inputBuffer, 0); inStream = new ByteArrayInputStream(inputBuffer); outStream = new ByteArrayOutputStream(); decodeBuffer(inStream, outStream); return (outStream.toByteArray()); } /** * Decode the contents of the inputstream into a buffer. */ public byte decodeBuffer(InputStream in)[] throws IOException { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); decodeBuffer(in, outStream); return (outStream.toByteArray()); } /** * Decode the contents of the String into a ByteBuffer. */ public ByteBuffer decodeBufferToByteBuffer(String inputString) throws IOException { return ByteBuffer.wrap(decodeBuffer(inputString)); } /** * Decode the contents of the inputStream into a ByteBuffer. */ public ByteBuffer decodeBufferToByteBuffer(InputStream in) throws IOException { return ByteBuffer.wrap(decodeBuffer(in)); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy