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