1 /* 2 * Copyright (c) 2012-2022, jcabi.com 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 1) Redistributions of source code must retain the above 8 * copyright notice, this list of conditions and the following 9 * disclaimer. 2) Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 3) Neither the name of the jcabi.com nor 13 * the names of its contributors may be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 19 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 28 * OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package com.jcabi.xml; 31 32 import java.io.BufferedInputStream; 33 import java.io.File; 34 import java.io.FileInputStream; 35 import java.io.FileNotFoundException; 36 import java.io.IOException; 37 import java.io.InputStream; 38 import java.net.URI; 39 import java.net.URL; 40 import java.nio.charset.StandardCharsets; 41 import java.util.Scanner; 42 import lombok.EqualsAndHashCode; 43 44 /** 45 * Represent a given resource (InputStream, URL/URI location content, File) 46 * as a string. UTF-8 encoding is used. 47 * 48 * <p>Objects of this class are immutable and thread-safe. 49 * 50 * @since 0.1 51 */ 52 @EqualsAndHashCode(of = "content") 53 final class TextResource { 54 55 /** 56 * The text representation. 57 */ 58 private final transient String content; 59 60 /** 61 * Private constructor, used for initializing the field text content. 62 * @param text The text content 63 */ 64 private TextResource(final String text) { 65 this.content = text; 66 } 67 68 /** 69 * Public constructor, represent an InputStream as a text resource. 70 * 71 * <p>The provided input stream will be closed automatically after 72 * getting data from it. 73 * @param stream Stream to represent as text. 74 */ 75 TextResource(final InputStream stream) { 76 this(TextResource.readAsString(stream)); 77 } 78 79 /** 80 * Public constructor, represent a File as a text resource. 81 * @param file File to represent as text. 82 * @throws FileNotFoundException If file not found 83 */ 84 TextResource(final File file) throws FileNotFoundException { 85 this( 86 TextResource.readAsString( 87 new BufferedInputStream(new FileInputStream(file)) 88 ) 89 ); 90 } 91 92 /** 93 * Public constructor, represent a URL location as a text resource. 94 * @param url URL to represent as text. 95 * @throws IOException If an IO problem occurs. 96 */ 97 TextResource(final URL url) throws IOException { 98 this(TextResource.readAsString(url)); 99 } 100 101 /** 102 * Public constructor, represent a URI location as a text resource. 103 * @param uri URI to represent as text. 104 * @throws IOException If an IO problem occurs. 105 */ 106 TextResource(final URI uri) throws IOException { 107 this(TextResource.readAsString(uri.toURL())); 108 } 109 110 @Override 111 public String toString() { 112 return this.content; 113 } 114 115 /** 116 * Reads an entire stream's contents into a string. 117 * @param stream The stream to read 118 * @return The stream content, in String form 119 */ 120 private static String readAsString(final InputStream stream) { 121 final Scanner scanner = new Scanner( 122 stream, StandardCharsets.UTF_8.name() 123 ).useDelimiter("\\A"); 124 final String result; 125 try { 126 if (scanner.hasNext()) { 127 result = scanner.next(); 128 } else { 129 result = ""; 130 } 131 } finally { 132 scanner.close(); 133 } 134 return result; 135 } 136 137 /** 138 * Reads URI contents into a string. 139 * @param url The URL to read 140 * @return The stream content, in String form 141 * @throws IOException if an IO exception occurs 142 */ 143 private static String readAsString(final URL url) throws IOException { 144 return TextResource.readAsString( 145 new BufferedInputStream(url.openStream()) 146 ); 147 } 148 }