View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.jcabi.xml;
6   
7   import java.io.BufferedInputStream;
8   import java.io.File;
9   import java.io.FileNotFoundException;
10  import java.io.IOException;
11  import java.io.InputStream;
12  import java.net.URI;
13  import java.net.URL;
14  import java.nio.charset.StandardCharsets;
15  import java.nio.file.Files;
16  import java.util.Scanner;
17  import lombok.EqualsAndHashCode;
18  
19  /**
20   * Represent a given resource (InputStream, URL/URI location content, File)
21   * as a string. UTF-8 encoding is used.
22   *
23   * <p>Objects of this class are immutable and thread-safe.
24   *
25   * @since 0.1
26   */
27  @EqualsAndHashCode(of = "content")
28  final class TextResource {
29  
30      /**
31       * The text representation.
32       */
33      private final transient String content;
34  
35      /**
36       * Private constructor, used for initializing the field text content.
37       * @param text The text content
38       */
39      private TextResource(final String text) {
40          this.content = text;
41      }
42  
43      /**
44       * Public constructor, represent an InputStream as a text resource.
45       *
46       * <p>The provided input stream will be closed automatically after
47       * getting data from it.
48       * @param stream Stream to represent as text.
49       */
50      TextResource(final InputStream stream) {
51          this(TextResource.readAsString(stream));
52      }
53  
54      /**
55       * Public constructor, represent a File as a text resource.
56       * @param file File to represent as text.
57       * @throws FileNotFoundException If file not found
58       */
59      TextResource(final File file) throws IOException {
60          this(
61              TextResource.readAsString(
62                  new BufferedInputStream(Files.newInputStream(file.toPath()))
63              )
64          );
65      }
66  
67      /**
68       * Public constructor, represent a URL location as a text resource.
69       * @param url URL to represent as text.
70       * @throws IOException If an IO problem occurs.
71       */
72      TextResource(final URL url) throws IOException {
73          this(TextResource.readAsString(url));
74      }
75  
76      /**
77       * Public constructor, represent a URI location as a text resource.
78       * @param uri URI to represent as text.
79       * @throws IOException If an IO problem occurs.
80       */
81      TextResource(final URI uri) throws IOException {
82          this(TextResource.readAsString(uri.toURL()));
83      }
84  
85      @Override
86      public String toString() {
87          return this.content;
88      }
89  
90      /**
91       * Reads an entire stream's contents into a string.
92       * @param stream The stream to read
93       * @return The stream content, in String form
94       */
95      private static String readAsString(final InputStream stream) {
96          final String result;
97          try (Scanner scanner = new Scanner(
98              stream, StandardCharsets.UTF_8.name()
99          ).useDelimiter("\\A")) {
100             if (scanner.hasNext()) {
101                 result = scanner.next();
102             } else {
103                 result = "";
104             }
105         }
106         return result;
107     }
108 
109     /**
110      * Reads URI contents into a string.
111      * @param url The URL to read
112      * @return The stream content, in String form
113      * @throws IOException if an IO exception occurs
114      */
115     private static String readAsString(final URL url) throws IOException {
116         return TextResource.readAsString(
117             new BufferedInputStream(url.openStream())
118         );
119     }
120 }