dk.netarkivet.common.utils.StreamUtils.java Source code

Java tutorial

Introduction

Here is the source code for dk.netarkivet.common.utils.StreamUtils.java

Source

/*
 * #%L
 * Netarchivesuite - common
 * %%
 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library,
 *             the National Library of France and the Austrian National Library.
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 * 
 * This program 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 Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
 * #L%
 */

package dk.netarkivet.common.utils;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;

import javax.servlet.jsp.JspWriter;

import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import dk.netarkivet.common.Constants;
import dk.netarkivet.common.exceptions.ArgumentNotValid;
import dk.netarkivet.common.exceptions.IOFailure;

/**
 * Utilities for handling streams.
 */
public class StreamUtils {

    /** logger for this class. */
    private static final Logger log = LoggerFactory.getLogger(StreamUtils.class);

    /** Constant for UTF-8. */
    private static final String UTF8_CHARSET = "UTF-8";

    /**
     * Will copy everything from input stream to jsp writer, closing input stream afterwards. Charset UTF-8 is assumed.
     *
     * @param in Inputstream to copy from
     * @param out JspWriter to copy to
     * @throws ArgumentNotValid if either parameter is null
     * @throws IOFailure if a read or write error happens during copy
     */
    public static void copyInputStreamToJspWriter(InputStream in, JspWriter out) {
        ArgumentNotValid.checkNotNull(in, "InputStream in");
        ArgumentNotValid.checkNotNull(out, "JspWriter out");

        byte[] buf = new byte[Constants.IO_BUFFER_SIZE];
        int read = 0;
        try {
            try {
                while ((read = in.read(buf)) != -1) {
                    out.write(new String(buf, UTF8_CHARSET), 0, read);
                }
            } finally {
                in.close();
            }
        } catch (IOException e) {
            String errMsg = "Trouble copying inputstream " + in + " to JspWriter " + out;
            log.warn(errMsg, e);
            throw new IOFailure(errMsg, e);
        }
    }

    /**
     * Will copy everything from input stream to output stream, closing input stream afterwards.
     *
     * @param in Inputstream to copy from
     * @param out Outputstream to copy to
     * @throws ArgumentNotValid if either parameter is null
     * @throws IOFailure if a read or write error happens during copy
     */
    public static void copyInputStreamToOutputStream(InputStream in, OutputStream out) {
        ArgumentNotValid.checkNotNull(in, "InputStream in");
        ArgumentNotValid.checkNotNull(out, "OutputStream out");

        try {
            try {
                if (in instanceof FileInputStream && out instanceof FileOutputStream) {
                    FileChannel inChannel = ((FileInputStream) in).getChannel();
                    FileChannel outChannel = ((FileOutputStream) out).getChannel();
                    long transferred = 0;
                    final long fileLength = inChannel.size();
                    do {
                        transferred += inChannel.transferTo(transferred,
                                Math.min(Constants.IO_CHUNK_SIZE, fileLength - transferred), outChannel);
                    } while (transferred < fileLength);
                } else {
                    byte[] buf = new byte[Constants.IO_BUFFER_SIZE];
                    int bytesRead;
                    while ((bytesRead = in.read(buf)) != -1) {
                        out.write(buf, 0, bytesRead);
                    }
                }
                out.flush();
            } finally {
                in.close();
            }
        } catch (IOException e) {
            String errMsg = "Trouble copying inputstream " + in + " to outputstream " + out;
            log.warn(errMsg, e);
            throw new IOFailure(errMsg, e);
        }
    }

    /**
     * Write document tree to stream. Note, the stream is flushed, but not closed.
     *
     * @param doc the document tree to save.
     * @param os the stream to write xml to
     * @throws IOFailure On trouble writing XML to stream.
     */
    public static void writeXmlToStream(Document doc, OutputStream os) {
        ArgumentNotValid.checkNotNull(doc, "Document doc");
        ArgumentNotValid.checkNotNull(doc, "OutputStream os");
        XMLWriter xwriter = null;
        try {
            try {
                OutputFormat format = OutputFormat.createPrettyPrint();
                format.setEncoding(UTF8_CHARSET);
                xwriter = new XMLWriter(os, format);
                xwriter.write(doc);
            } finally {
                if (xwriter != null) {
                    xwriter.close();
                }
                os.flush();
            }
        } catch (IOException e) {
            String errMsg = "Unable to write XML to stream";
            log.warn(errMsg, e);
            throw new IOFailure(errMsg, e);
        }
    }

    /**
     * Reads an input stream and returns it as a string.
     *
     * @param in The input stream.
     * @return The string content of the input stream in the UTF8-charset.
     * @throws ArgumentNotValid If the input stream is null.
     * @throws IOFailure If an IOException is caught while reading the inputstream.
     */
    public static String getInputStreamAsString(InputStream in) throws ArgumentNotValid, IOFailure {
        ArgumentNotValid.checkNotNull(in, "InputStream in");

        StringBuilder res = new StringBuilder();
        byte[] buf = new byte[Constants.IO_BUFFER_SIZE];
        int read = 0;
        try {
            try {
                while ((read = in.read(buf)) != -1) {
                    res.append(new String(buf, UTF8_CHARSET), 0, read);
                }
            } finally {
                in.close();
            }
        } catch (IOException e) {
            String errMsg = "Trouble reading inputstream '" + in + "'";
            log.warn(errMsg, e);
            throw new IOFailure(errMsg, e);
        }

        return res.toString();
    }

    /**
     * Convert inputStream to byte array.
     *
     * @param data inputstream
     * @param dataLength length of inputstream (must be larger than 0)
     * @return byte[] containing data in inputstream
     */
    public static byte[] inputStreamToBytes(InputStream data, int dataLength) {
        ArgumentNotValid.checkNotNull(data, "data");
        ArgumentNotValid.checkNotNegative(dataLength, "dataLength");
        byte[] contents = new byte[dataLength];
        try {
            int read = data.read(contents, 0, dataLength);
            if (dataLength != read) {
                log.debug("Only read {} bytes out of the {} bytes requested", read, dataLength);
            }
        } catch (IOException e) {
            throw new IOFailure("Unable to convert inputstream to byte array", e);
        }
        return contents;
    }

}