001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017 018package org.apache.logging.log4j.core.config; 019 020import java.io.ByteArrayInputStream; 021import java.io.ByteArrayOutputStream; 022import java.io.File; 023import java.io.FileInputStream; 024import java.io.IOException; 025import java.io.InputStream; 026import java.net.URL; 027 028import org.apache.logging.log4j.core.util.Assert; 029 030/** 031 * Represents the source for the logging configuration. 032 */ 033public class ConfigurationSource { 034 public static final ConfigurationSource NULL_SOURCE = new ConfigurationSource(new byte[0]); 035 036 private final File file; 037 private final URL url; 038 private final String location; 039 private final InputStream stream; 040 private final byte[] data; 041 042 /** 043 * Returns the contents of the specified {@code InputStream} as a byte array. 044 * 045 * @param inputStream the stream to read 046 * @return the contents of the specified stream 047 * @throws IOException if a problem occurred reading from the stream 048 */ 049 private static byte[] toByteArray(final InputStream inputStream) throws IOException { 050 final int buffSize = Math.max(4096, inputStream.available()); 051 final ByteArrayOutputStream contents = new ByteArrayOutputStream(buffSize); 052 final byte[] buff = new byte[buffSize]; 053 054 int length = inputStream.read(buff); 055 while (length > 0) { 056 contents.write(buff, 0, length); 057 length = inputStream.read(buff); 058 } 059 return contents.toByteArray(); 060 } 061 062 /** 063 * Constructs a new {@code ConfigurationSource} with the specified input stream. Since the stream is the only source 064 * of data, this constructor makes a copy of the stream contents. 065 * 066 * @param stream the input stream 067 * @throws IOException if an exception occurred reading from the specified stream 068 */ 069 public ConfigurationSource(final InputStream stream) throws IOException { 070 this(toByteArray(stream)); 071 } 072 073 private ConfigurationSource(final byte[] data) { 074 this.data = Assert.requireNonNull(data, "data is null"); 075 this.stream = new ByteArrayInputStream(data); 076 this.file = null; 077 this.url = null; 078 this.location = null; 079 } 080 081 /** 082 * Constructs a new {@code ConfigurationSource} with the specified input stream that originated from the specified 083 * file. 084 * 085 * @param stream the input stream 086 * @param file the file where the input stream originated 087 */ 088 public ConfigurationSource(final InputStream stream, final File file) { 089 this.stream = Assert.requireNonNull(stream, "stream is null"); 090 this.file = Assert.requireNonNull(file, "file is null"); 091 this.location = file.getAbsolutePath(); 092 this.url = null; 093 this.data = null; 094 } 095 096 /** 097 * Constructs a new {@code ConfigurationSource} with the specified input stream that originated from the specified 098 * url. 099 * 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}