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.logging.log4j.core.config;
19  
20  import java.io.ByteArrayInputStream;
21  import java.io.ByteArrayOutputStream;
22  import java.io.File;
23  import java.io.FileInputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.net.URL;
27  import java.util.Objects;
28  
29  /**
30   * Represents the source for the logging configuration.
31   */
32  public class ConfigurationSource {
33      public static final ConfigurationSource NULL_SOURCE = new ConfigurationSource(new byte[0]);
34  
35      private final File file;
36      private final URL url;
37      private final String location;
38      private final InputStream stream;
39      private final byte[] data;
40  
41      /**
42       * Returns the contents of the specified {@code InputStream} as a byte array.
43       * 
44       * @param inputStream the stream to read
45       * @return the contents of the specified stream
46       * @throws IOException if a problem occurred reading from the stream
47       */
48      private static byte[] toByteArray(final InputStream inputStream) throws IOException {
49          final int buffSize = Math.max(4096, inputStream.available());
50          final ByteArrayOutputStream contents = new ByteArrayOutputStream(buffSize);
51          final byte[] buff = new byte[buffSize];
52  
53          int length = inputStream.read(buff);
54          while (length > 0) {
55              contents.write(buff, 0, length);
56              length = inputStream.read(buff);
57          }
58          return contents.toByteArray();
59      }
60  
61      /**
62       * Constructs a new {@code ConfigurationSource} with the specified input stream. Since the stream is the only source
63       * of data, this constructor makes a copy of the stream contents.
64       * 
65       * @param stream the input stream
66       * @throws IOException if an exception occurred reading from the specified stream
67       */
68      public ConfigurationSource(final InputStream stream) throws IOException {
69          this(toByteArray(stream));
70      }
71  
72      private ConfigurationSource(final byte[] data) {
73          this.data = Objects.requireNonNull(data, "data is null");
74          this.stream = new ByteArrayInputStream(data);
75          this.file = null;
76          this.url = null;
77          this.location = null;
78      }
79  
80      /**
81       * Constructs a new {@code ConfigurationSource} with the specified input stream that originated from the specified
82       * file.
83       * 
84       * @param stream the input stream
85       * @param file the file where the input stream originated
86       */
87      public ConfigurationSource(final InputStream stream, final File file) {
88          this.stream = Objects.requireNonNull(stream, "stream is null");
89          this.file = Objects.requireNonNull(file, "file is null");
90          this.location = file.getAbsolutePath();
91          this.url = null;
92          this.data = null;
93      }
94  
95      /**
96       * Constructs a new {@code ConfigurationSource} with the specified input stream that originated from the specified
97       * url.
98       * 
99       * @param stream the input stream
100      * @param url the URL where the input stream originated
101      */
102     public ConfigurationSource(final InputStream stream, final URL url) {
103         this.stream = Objects.requireNonNull(stream, "stream is null");
104         this.url = Objects.requireNonNull(url, "URL is null");
105         this.location = url.toString();
106         this.file = null;
107         this.data = null;
108     }
109 
110     /**
111      * Returns the file configuration source, or {@code null} if this configuration source is based on an URL or has
112      * neither a file nor an URL.
113      * 
114      * @return the configuration source file, or {@code null}
115      */
116     public File getFile() {
117         return file;
118     }
119 
120     /**
121      * Returns the configuration source URL, or {@code null} if this configuration source is based on a file or has
122      * neither a file nor an URL.
123      * 
124      * @return the configuration source URL, or {@code null}
125      */
126     public URL getURL() {
127         return url;
128     }
129 
130     /**
131      * Returns a string describing the configuration source file or URL, or {@code null} if this configuration source
132      * has neither a file nor an URL.
133      * 
134      * @return a string describing the configuration source file or URL, or {@code null}
135      */
136     public String getLocation() {
137         return location;
138     }
139 
140     /**
141      * Returns the input stream that this configuration source was constructed with.
142      * 
143      * @return the input stream that this configuration source was constructed with.
144      */
145     public InputStream getInputStream() {
146         return stream;
147     }
148 
149     /**
150      * Returns a new {@code ConfigurationSource} whose input stream is reset to the beginning.
151      * 
152      * @return a new {@code ConfigurationSource}
153      * @throws IOException if a problem occurred while opening the new input stream
154      */
155     public ConfigurationSource resetInputStream() throws IOException {
156         if (file != null) {
157             return new ConfigurationSource(new FileInputStream(file), file);
158         } else if (url != null) {
159             return new ConfigurationSource(url.openStream(), url);
160         } else {
161             return new ConfigurationSource(data);
162         }
163     }
164 
165     @Override
166     public String toString() {
167         if (location != null) {
168             return location;
169         }
170         if (this == NULL_SOURCE) {
171             return "NULL_SOURCE";
172         }
173         final int length = data == null ? -1 : data.length;
174         return "stream (" + length + " bytes, unknown location)";
175     }
176 }