+++ /dev/null
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.log4j.helpers;
-
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.net.URL;
-import java.util.Properties;
-
-import org.apache.log4j.Level;
-import org.apache.log4j.PropertyConfigurator;
-import org.apache.log4j.spi.Configurator;
-import org.apache.log4j.spi.LoggerRepository;
-
-// Contributors: Avy Sharell (sharell@online.fr)
-// Matthieu Verbert (mve@zurich.ibm.com)
-// Colin Sampaleanu
-
-/**
- A convenience class to convert property values to specific types.
-
- @author Ceki Gülcü
- @author Simon Kitching;
- @author Anders Kristensen
-*/
-public class OptionConverter {
-
- static String DELIM_START = "${";
- static char DELIM_STOP = '}';
- static int DELIM_START_LEN = 2;
- static int DELIM_STOP_LEN = 1;
-
- /** OptionConverter is a static class. */
- private OptionConverter() {}
-
- public
- static
- String[] concatanateArrays(String[] l, String[] r) {
- int len = l.length + r.length;
- String[] a = new String[len];
-
- System.arraycopy(l, 0, a, 0, l.length);
- System.arraycopy(r, 0, a, l.length, r.length);
-
- return a;
- }
-
- public
- static
- String convertSpecialChars(String s) {
- char c;
- int len = s.length();
- StringBuffer sbuf = new StringBuffer(len);
-
- int i = 0;
- while(i < len) {
- c = s.charAt(i++);
- if (c == '\\') {
- c = s.charAt(i++);
- if(c == 'n') {
- c = '\n';
- } else if(c == 'r') {
- c = '\r';
- } else if(c == 't') {
- c = '\t';
- } else if(c == 'f') {
- c = '\f';
- } else if(c == '\b') {
- c = '\b';
- } else if(c == '\"') {
- c = '\"';
- } else if(c == '\'') {
- c = '\'';
- } else if(c == '\\') {
- c = '\\';
- }
- }
- sbuf.append(c);
- }
- return sbuf.toString();
- }
-
-
- /**
- Very similar to <code>System.getProperty</code> except
- that the {@link SecurityException} is hidden.
-
- @param key The key to search for.
- @param def The default value to return.
- @return the string value of the system property, or the default
- value if there is no property with that key.
-
- @since 1.1 */
- public
- static
- String getSystemProperty(String key, String def) {
- try {
- return System.getProperty(key, def);
- } catch(Throwable e) { // MS-Java throws com.ms.security.SecurityExceptionEx
- LogLog.debug("Was not allowed to read system property \""+key+"\".");
- return def;
- }
- }
-
-
- public
- static
- Object instantiateByKey(Properties props, String key, Class superClass,
- Object defaultValue) {
-
- // Get the value of the property in string form
- String className = findAndSubst(key, props);
- if(className == null) {
- LogLog.error("Could not find value for key " + key);
- return defaultValue;
- }
- // Trim className to avoid trailing spaces that cause problems.
- return OptionConverter.instantiateByClassName(className.trim(), superClass,
- defaultValue);
- }
-
- /**
- If <code>value</code> is "true", then <code>true</code> is
- returned. If <code>value</code> is "false", then
- <code>true</code> is returned. Otherwise, <code>default</code> is
- returned.
-
- <p>Case of value is unimportant. */
- public
- static
- boolean toBoolean(String value, boolean dEfault) {
- if(value == null) {
- return dEfault;
- }
- String trimmedVal = value.trim();
- if("true".equalsIgnoreCase(trimmedVal)) {
- return true;
- }
- if("false".equalsIgnoreCase(trimmedVal)) {
- return false;
- }
- return dEfault;
- }
-
- public
- static
- int toInt(String value, int dEfault) {
- if(value != null) {
- String s = value.trim();
- try {
- return Integer.valueOf(s).intValue();
- }
- catch (NumberFormatException e) {
- LogLog.error("[" + s + "] is not in proper int form.");
- e.printStackTrace();
- }
- }
- return dEfault;
- }
-
- /**
- Converts a standard or custom priority level to a Level
- object. <p> If <code>value</code> is of form
- "level#classname", then the specified class' toLevel method
- is called to process the specified level string; if no '#'
- character is present, then the default {@link org.apache.log4j.Level}
- class is used to process the level value.
-
- <p>As a special case, if the <code>value</code> parameter is
- equal to the string "NULL", then the value <code>null</code> will
- be returned.
-
- <p> If any error occurs while converting the value to a level,
- the <code>defaultValue</code> parameter, which may be
- <code>null</code>, is returned.
-
- <p> Case of <code>value</code> is insignificant for the level level, but is
- significant for the class name part, if present.
-
- @since 1.1 */
- public
- static
- Level toLevel(String value, Level defaultValue) {
- if(value == null) {
- return defaultValue;
- }
-
- value = value.trim();
-
- int hashIndex = value.indexOf('#');
- if (hashIndex == -1) {
- if("NULL".equalsIgnoreCase(value)) {
- return null;
- } else {
- // no class name specified : use standard Level class
- return Level.toLevel(value, defaultValue);
- }
- }
-
- Level result = defaultValue;
-
- String clazz = value.substring(hashIndex+1);
- String levelName = value.substring(0, hashIndex);
-
- // This is degenerate case but you never know.
- if("NULL".equalsIgnoreCase(levelName)) {
- return null;
- }
-
- LogLog.debug("toLevel" + ":class=[" + clazz + "]"
- + ":pri=[" + levelName + "]");
-
- try {
- Class customLevel = Loader.loadClass(clazz);
-
- // get a ref to the specified class' static method
- // toLevel(String, org.apache.log4j.Level)
- Class[] paramTypes = new Class[] { String.class,
- org.apache.log4j.Level.class
- };
- java.lang.reflect.Method toLevelMethod =
- customLevel.getMethod("toLevel", paramTypes);
-
- // now call the toLevel method, passing level string + default
- Object[] params = new Object[] {levelName, defaultValue};
- Object o = toLevelMethod.invoke(null, params);
-
- result = (Level) o;
- } catch(ClassNotFoundException e) {
- LogLog.warn("custom level class [" + clazz + "] not found.");
- } catch(NoSuchMethodException e) {
- LogLog.warn("custom level class [" + clazz + "]"
- + " does not have a class function toLevel(String, Level)", e);
- } catch(java.lang.reflect.InvocationTargetException e) {
- if (e.getTargetException() instanceof InterruptedException
- || e.getTargetException() instanceof InterruptedIOException) {
- Thread.currentThread().interrupt();
- }
- LogLog.warn("custom level class [" + clazz + "]"
- + " could not be instantiated", e);
- } catch(ClassCastException e) {
- LogLog.warn("class [" + clazz
- + "] is not a subclass of org.apache.log4j.Level", e);
- } catch(IllegalAccessException e) {
- LogLog.warn("class ["+clazz+
- "] cannot be instantiated due to access restrictions", e);
- } catch(RuntimeException e) {
- LogLog.warn("class ["+clazz+"], level ["+levelName+
- "] conversion failed.", e);
- }
- return result;
- }
-
- public
- static
- long toFileSize(String value, long dEfault) {
- if(value == null) {
- return dEfault;
- }
-
- String s = value.trim().toUpperCase();
- long multiplier = 1;
- int index;
-
- if((index = s.indexOf("KB")) != -1) {
- multiplier = 1024;
- s = s.substring(0, index);
- }
- else if((index = s.indexOf("MB")) != -1) {
- multiplier = 1024*1024;
- s = s.substring(0, index);
- }
- else if((index = s.indexOf("GB")) != -1) {
- multiplier = 1024*1024*1024;
- s = s.substring(0, index);
- }
- if(s != null) {
- try {
- return Long.valueOf(s).longValue() * multiplier;
- }
- catch (NumberFormatException e) {
- LogLog.error("[" + s + "] is not in proper int form.");
- LogLog.error("[" + value + "] not in expected format.", e);
- }
- }
- return dEfault;
- }
-
- /**
- Find the value corresponding to <code>key</code> in
- <code>props</code>. Then perform variable substitution on the
- found value.
-
- */
- public
- static
- String findAndSubst(String key, Properties props) {
- String value = props.getProperty(key);
- if(value == null) {
- return null;
- }
-
- try {
- return substVars(value, props);
- } catch(IllegalArgumentException e) {
- LogLog.error("Bad option value ["+value+"].", e);
- return value;
- }
- }
-
- /**
- Instantiate an object given a class name. Check that the
- <code>className</code> is a subclass of
- <code>superClass</code>. If that test fails or the object could
- not be instantiated, then <code>defaultValue</code> is returned.
-
- @param className The fully qualified class name of the object to instantiate.
- @param superClass The class to which the new object should belong.
- @param defaultValue The object to return in case of non-fulfillment
- */
- public
- static
- Object instantiateByClassName(String className, Class superClass,
- Object defaultValue) {
- if(className != null) {
- try {
- Class classObj = Loader.loadClass(className);
- if(!superClass.isAssignableFrom(classObj)) {
- LogLog.error("A \""+className+"\" object is not assignable to a \""+
- superClass.getName() + "\" variable.");
- LogLog.error("The class \""+ superClass.getName()+"\" was loaded by ");
- LogLog.error("["+superClass.getClassLoader()+"] whereas object of type ");
- LogLog.error("\"" +classObj.getName()+"\" was loaded by ["
- +classObj.getClassLoader()+"].");
- return defaultValue;
- }
- return classObj.newInstance();
- } catch (ClassNotFoundException e) {
- LogLog.error("Could not instantiate class [" + className + "].", e);
- } catch (IllegalAccessException e) {
- LogLog.error("Could not instantiate class [" + className + "].", e);
- } catch (InstantiationException e) {
- LogLog.error("Could not instantiate class [" + className + "].", e);
- } catch (RuntimeException e) {
- LogLog.error("Could not instantiate class [" + className + "].", e);
- }
- }
- return defaultValue;
- }
-
-
- /**
- Perform variable substitution in string <code>val</code> from the
- values of keys found in the system propeties.
-
- <p>The variable substitution delimeters are <b>${</b> and <b>}</b>.
-
- <p>For example, if the System properties contains "key=value", then
- the call
- <pre>
- String s = OptionConverter.substituteVars("Value of key is ${key}.");
- </pre>
-
- will set the variable <code>s</code> to "Value of key is value.".
-
- <p>If no value could be found for the specified key, then the
- <code>props</code> parameter is searched, if the value could not
- be found there, then substitution defaults to the empty string.
-
- <p>For example, if system propeties contains no value for the key
- "inexistentKey", then the call
-
- <pre>
- String s = OptionConverter.subsVars("Value of inexistentKey is [${inexistentKey}]");
- </pre>
- will set <code>s</code> to "Value of inexistentKey is []"
-
- <p>An {@link java.lang.IllegalArgumentException} is thrown if
- <code>val</code> contains a start delimeter "${" which is not
- balanced by a stop delimeter "}". </p>
-
- <p><b>Author</b> Avy Sharell</a></p>
-
- @param val The string on which variable substitution is performed.
- @throws IllegalArgumentException if <code>val</code> is malformed.
-
- */
- public static
- String substVars(String val, Properties props) throws
- IllegalArgumentException {
-
- StringBuffer sbuf = new StringBuffer();
-
- int i = 0;
- int j, k;
-
- while(true) {
- j=val.indexOf(DELIM_START, i);
- if(j == -1) {
- // no more variables
- if(i==0) { // this is a simple string
- return val;
- } else { // add the tail string which contails no variables and return the result.
- sbuf.append(val.substring(i, val.length()));
- return sbuf.toString();
- }
- } else {
- sbuf.append(val.substring(i, j));
- k = val.indexOf(DELIM_STOP, j);
- if(k == -1) {
- throw new IllegalArgumentException('"'+val+
- "\" has no closing brace. Opening brace at position " + j
- + '.');
- } else {
- j += DELIM_START_LEN;
- String key = val.substring(j, k);
- // first try in System properties
- String replacement = getSystemProperty(key, null);
- // then try props parameter
- if(replacement == null && props != null) {
- replacement = props.getProperty(key);
- }
-
- if(replacement != null) {
- // Do variable substitution on the replacement string
- // such that we can solve "Hello ${x2}" as "Hello p1"
- // the where the properties are
- // x1=p1
- // x2=${x1}
- String recursiveReplacement = substVars(replacement, props);
- sbuf.append(recursiveReplacement);
- }
- i = k + DELIM_STOP_LEN;
- }
- }
- }
- }
-
- /**
- * Configure log4j given an {@link InputStream}.
- *
- * <p>
- * The InputStream will be interpreted by a new instance of a log4j configurator.
- * </p>
- * <p>
- * All configurations steps are taken on the <code>hierarchy</code> passed as a parameter.
- * </p>
- *
- * @param inputStream
- * The configuration input stream.
- * @param clazz
- * The class name, of the log4j configurator which will parse the <code>inputStream</code>. This must be a
- * subclass of {@link Configurator}, or null. If this value is null then a default configurator of
- * {@link PropertyConfigurator} is used.
- * @param hierarchy
- * The {@link org.apache.log4j.Hierarchy} to act on.
- * @since 1.2.17
- */
-
-static
-public
-void selectAndConfigure(InputStream inputStream, String clazz, LoggerRepository hierarchy) {
-Configurator configurator = null;
-
-if(clazz != null) {
- LogLog.debug("Preferred configurator class: " + clazz);
- configurator = (Configurator) instantiateByClassName(clazz,
- Configurator.class,
- null);
- if(configurator == null) {
- LogLog.error("Could not instantiate configurator ["+clazz+"].");
- return;
- }
-} else {
- configurator = new PropertyConfigurator();
-}
-
-configurator.doConfigure(inputStream, hierarchy);
-}
-
-
- /**
- Configure log4j given a URL.
-
- <p>The url must point to a file or resource which will be interpreted by
- a new instance of a log4j configurator.
-
- <p>All configurations steps are taken on the
- <code>hierarchy</code> passed as a parameter.
-
- <p>
- @param url The location of the configuration file or resource.
- @param clazz The classname, of the log4j configurator which will parse
- the file or resource at <code>url</code>. This must be a subclass of
- {@link Configurator}, or null. If this value is null then a default
- configurator of {@link PropertyConfigurator} is used, unless the
- filename pointed to by <code>url</code> ends in '.xml', in which case
- {@link org.apache.log4j.xml.DOMConfigurator} is used.
- @param hierarchy The {@link org.apache.log4j.Hierarchy} to act on.
-
- @since 1.1.4 */
-
- static
- public
- void selectAndConfigure(URL url, String clazz, LoggerRepository hierarchy) {
- Configurator configurator = null;
- String filename = url.getFile();
-
- if(clazz == null && filename != null && filename.endsWith(".xml")) {
- clazz = "org.apache.log4j.xml.DOMConfigurator";
- }
-
- if(clazz != null) {
- LogLog.debug("Preferred configurator class: " + clazz);
- configurator = (Configurator) instantiateByClassName(clazz,
- Configurator.class,
- null);
- if(configurator == null) {
- LogLog.error("Could not instantiate configurator ["+clazz+"].");
- return;
- }
- } else {
- configurator = new PropertyConfigurator();
- }
-
- configurator.doConfigure(url, hierarchy);
- }
-}