/* * Copyright 2005-2015 by BerryWorks Software, LLC. All rights reserved. * * This file is part of EDIReader. You may obtain a license for its use directly from * BerryWorks Software, and you may also choose to use this software under the terms of the * GPL version 3. Other products in the EDIReader software suite are available only by licensing * with BerryWorks. Only those files bearing the GPL statement below are available under the GPL. * * EDIReader is free software: you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * EDIReader is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with EDIReader. If not, * see <http://www.gnu.org/licenses/>. */ package com.berryworks.edireader.util; import com.berryworks.edireader.util.base64.AbstractEncoder; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; /** * Encode char data using base-64 conventions * before presenting that data to a SAX ContentHandler. */ public class ContentHandlerBase64Encoder extends AbstractEncoder { private ContentHandler contentHandler; private ByteBuffer base64Bytes; public void encode(char[] dataObject, ContentHandler contentHandler) { this.contentHandler = contentHandler; CharBuffer charBuffer = CharBuffer.wrap(dataObject); // Allocate a modest sized non-direct ByteBuffer to receive the // bytes as they are encoded from the chars ByteBuffer byteBuffer = ByteBuffer.allocate(100); // Allocate a similar ByteBuffer to receive the bytes as they are emitted // by the Base 64 encoder. base64Bytes = ByteBuffer.allocate(100); // Use an encoder repeatedly until all of the chars have been encoded as bytes // and presented as input for base 64 encoding. CharsetEncoder encoder = charset.newEncoder(); while (true) { CoderResult coderResult = encoder.encode(charBuffer, byteBuffer, true); if (coderResult.isError()) throw new RuntimeException("Unrecoverable failure in Base64 encoding"); byteBuffer.flip(); while (byteBuffer.hasRemaining()) consume(byteBuffer.get()); if (coderResult.isUnderflow()) break; byteBuffer.clear(); } endOfData(); feedContentHandler(); } @Override protected void emit(byte b) { if (!base64Bytes.hasRemaining()) { // Whenever the ByteBuffer gets full, use the CharSetEncoder // to turn the bytes into chars in a CharBuffer. // Whenever the CharBuffer gets full, give those chars // to the SAX ContentHandler. feedContentHandler(); base64Bytes.clear(); } // Put the byte into a byteBuffer. base64Bytes.put(b); } private void feedContentHandler() { base64Bytes.flip(); CharBuffer charBuffer = charset.decode(base64Bytes); try { contentHandler.characters(charBuffer.array(), 0, charBuffer.length()); } catch (SAXException e) { throw new RuntimeException("Unrecoverable failure in Base64 encoding"); } } }