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