All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.log4j.helpers.OptionConverter Maven / Gradle / Ivy

There is a newer version: 6.1.3
Show newest version
/*
 * 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 ([email protected])
//                 Matthieu Verbert ([email protected])
//                 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();
	StringBuilder sbuf = new StringBuilder(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 System.getProperty 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 value is "true", then true is returned. If
     * value is "false", then true is returned. Otherwise,
     * default is returned.
     * 
     * 

* 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. *

* If value 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. * *

* As a special case, if the value parameter is equal to the string * "NULL", then the value null will be returned. * *

* If any error occurs while converting the value to a level, the * defaultValue parameter, which may be null, is * returned. * *

* Case of value 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) 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 key in props. 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 * className is a subclass of superClass. If that test * fails or the object could not be instantiated, then defaultValue * 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 val from the values of * keys found in the system propeties. * *

* The variable substitution delimeters are ${ and }. * *

* For example, if the System properties contains "key=value", then the call * *

     * String s = OptionConverter.substituteVars("Value of key is ${key}.");
     * 
* * will set the variable s to "Value of key is value.". * *

* If no value could be found for the specified key, then the props * parameter is searched, if the value could not be found there, then * substitution defaults to the empty string. * *

* For example, if system propeties contains no value for the key * "inexistentKey", then the call * *

     * String s = OptionConverter.subsVars("Value of inexistentKey is [${inexistentKey}]");
     * 
* * will set s to "Value of inexistentKey is []" * *

* An {@link java.lang.IllegalArgumentException} is thrown if val * contains a start delimeter "${" which is not balanced by a stop delimeter * "}". *

* *

* Author Avy Sharell *

* * @param val The string on which variable substitution is performed. * @throws IllegalArgumentException if val is malformed. * */ public static String substVars(String val, Properties props) throws IllegalArgumentException { StringBuilder sbuf = new StringBuilder(); 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}. * *

* The InputStream will be interpreted by a new instance of a log4j * configurator. *

*

* All configurations steps are taken on the hierarchy passed as a * parameter. *

* * @param inputStream The configuration input stream. * @param clazz The class name, of the log4j configurator which will parse * the inputStream. 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. * *

* The url must point to a file or resource which will be interpreted by a new * instance of a log4j configurator. * *

* All configurations steps are taken on the hierarchy passed as a * parameter. * *

* * @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 url. 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 url 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); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy