View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *  http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.any23.util;
    19
    20  import org.apache.commons.io.ByteOrderMark;
    21  import org.apache.commons.io.input.BOMInputStream;
    22  import org.apache.xerces.impl.io.MalformedByteSequenceException;
    23  import org.slf4j.Logger;
    24  import org.slf4j.LoggerFactory;
    25  import org.w3c.dom.Document;
    26  import org.xml.sax.SAXException;
    27
    28  import java.io.BufferedReader;
    29  import java.io.ByteArrayInputStream;
    30  import java.io.ByteArrayOutputStream;
    31  import java.io.Closeable;
    32  import java.io.IOException;
    33  import java.io.InputStream;
    34  import java.io.InputStreamReader;
    35  import java.nio.charset.StandardCharsets;
    36  import java.util.ArrayList;
    37  import java.util.List;
    38
    39  import javax.xml.parsers.DocumentBuilder;
    40  import javax.xml.parsers.DocumentBuilderFactory;
    41  import javax.xml.parsers.ParserConfigurationException;
    42  import javax.xml.transform.Result;
    43  import javax.xml.transform.Source;
    44  import javax.xml.transform.TransformerConfigurationException;
    45  import javax.xml.transform.TransformerException;
    46  import javax.xml.transform.TransformerFactory;
    47  import javax.xml.transform.TransformerFactoryConfigurationError;
    48  import javax.xml.transform.dom.DOMSource;
    49  import javax.xml.transform.stream.StreamResult;
    50
    51  /**
    52   * Contains general utility functions for handling streams.
    53   *
    54   * @author Michele Mostarda (mostarda@fbk.eu)
    55   */
    56  public class StreamUtils {
    57
    58      private static final Logger logger = LoggerFactory.getLogger(StreamUtils.class);
    59
    60      private StreamUtils() {
    61      }
    62
    63      /**
    64       * Returns all the lines read from an input stream.
    65       *
    66       * @param is
    67       *            input stream.
    68       *
    69       * @return list of not <code>null</code> lines.
    70       *
    71       * @throws IOException
    72       *             if an error occurs while consuming the <code>is</code> stream.
    73       */
    74      public static String[] asLines(InputStream is) throws IOException {
    75          final BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
    76          final List<String> lines = new ArrayList<String>();
    77          try {
    78              String line;
    79              while ((line = br.readLine()) != null) {
    80                  lines.add(line);
    81              }
    82              return lines.toArray(new String[lines.size()]);
    83          } finally {
    84              closeGracefully(br);
    85          }
    86      }
    87
    88      /**
    89       * Returns the string content of a stream.
    90       *
    91       * @param is
    92       *            input stream.
    93       * @param preserveNL
    94       *            preserves new line chars.
    95       *
    96       * @return the string content.
    97       *
    98       * @throws IOException
    99       *             if an error occurs while consuming the <code>is</code> stream.
    100      */
    101     public static String asString(InputStream is, boolean preserveNL) throws IOException {
    102         if (is == null) {
    103             throw new NullPointerException("input stream is null.");
    104         }
    105         final BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
    106         try {
    107             final StringBuilder content = new StringBuilder();
    108             String line;
    109             while ((line = br.readLine()) != null) {
    110                 content.append(line);
    111                 if (preserveNL)
    112                     content.append('\n');
    113             }
    114             return content.toString();
    115         } finally {
    116             closeGracefully(br);
    117         }
    118     }
    119
    120     /**
    121      * Returns the string content of a stream, new line chars will be removed.
    122      *
    123      * @param is
    124      *            input stream.
    125      *
    126      * @return the string content.
    127      *
    128      * @throws IOException
    129      *             if an error occurs while consuming the <code>is</code> stream.
    130      */
    131     public static String asString(InputStream is) throws IOException {
    132         return asString(is, false);
    133     }
    134
    135     /**
    136      * Closes the closable interface and reports error if any.
    137      *
    138      * @param closable
    139      *            the closable object to be closed.
    140      */
    141     public static void closeGracefully(Closeable closable) {
    142         if (closable != null) {
    143             try {
    144                 closable.close();
    145             } catch (Exception e) {
    146                 logger.error("Error while closing object " + closable, e);
    147             }
    148         }
    149     }
    150
    151     /**
    152      * Converts a {@link org.w3c.dom.Document} to an {@link java.io.InputStream}
    153      *
    154      * @param doc
    155      *            the {@link org.w3c.dom.Document} to convert
    156      *
    157      * @return an {@link java.io.InputStream} representing the contents of the input {@link org.w3c.dom.Document}
    158      *
    159      * @throws TransformerFactoryConfigurationError
    160      *             thrown when there is a problem with configuration with the Transformer Factories
    161      * @throws TransformerConfigurationException
    162      *             thrown when a serious configuration error exists
    163      */
    164     public static InputStream documentToInputStream(Document doc)
    165             throws TransformerConfigurationException, TransformerFactoryConfigurationError {
    166         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    167         Source xmlSource = new DOMSource(doc);
    168         Result outputTarget = new StreamResult(outputStream);
    169         try {
    170             TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
    171         } catch (TransformerException e) {
    172             logger.error("Error during transformation: {}", e);
    173         }
    174         return new ByteArrayInputStream(outputStream.toByteArray());
    175     }
    176
    177     public static Document inputStreamToDocument(InputStream is) throws MalformedByteSequenceException {
    178         DocumentBuilderFactory factory = null;
    179         DocumentBuilder builder = null;
    180         Document doc = null;
    181
    182         try {
    183             factory = DocumentBuilderFactory.newInstance();
    184             factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    185             builder = factory.newDocumentBuilder();
    186         } catch (ParserConfigurationException e) {
    187             logger.error("Error converting InputStream to Document: {}", e);
    188         }
    189
    190         try {
    191             BOMInputStream bomIn = new BOMInputStream(is, ByteOrderMark.UTF_8, ByteOrderMark.UTF_16BE,
    192                     ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_32BE, ByteOrderMark.UTF_32LE);
    193             if (bomIn.hasBOM()) {
    194                 @SuppressWarnings("unused")
    195                 int firstNonBOMByte = bomIn.read(); // Skips BOM
    196             }
    197             doc = builder.parse(bomIn);
    198         } catch (SAXException | IOException e) {
    199             logger.error("Error converting InputStream to Document: {}", e);
    200         }
    201         return doc;
    202     }
    203 }