You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-cvs@jakarta.apache.org by an...@apache.org on 2001/03/19 13:31:42 UTC

cvs commit: jakarta-log4j/org/apache/log4j/config PropertyGetter.java PropertyPrinter.java PropertySetter.java PropertySetterException.java

anders      01/03/19 04:31:42

  Added:       org/apache/log4j/config PropertyGetter.java
                        PropertyPrinter.java PropertySetter.java
                        PropertySetterException.java
  Log:
  Utility classes for handling new JavaBeans style configuration.
  
  Revision  Changes    Path
  1.1                  jakarta-log4j/org/apache/log4j/config/PropertyGetter.java
  
  Index: PropertyGetter.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software
   * License version 1.1, a copy of which has been included with this
   * distribution in the LICENSE.APL file.
   */
  
  package org.apache.log4j.config;
  
  import java.beans.*;
  import java.io.*;
  import java.lang.reflect.*;
  import java.util.*;
  import org.apache.log4j.Appender;
  import org.apache.log4j.Priority;
  import org.apache.log4j.helpers.LogLog;
  
  /**
     Used for inferring configuration information for a log4j's component.
     
     @author  Anders Kristensen
   */
  public class PropertyGetter {
    protected static final Object[] NULL_ARG = new Object[] {};
    protected Object obj;
    protected PropertyDescriptor[] props;
    
    public interface PropertyCallback {
      void foundProperty(Object obj, String prefix, String name, Object value);
    }
    
    /**
      Create a new PropertySetter for the specified Object. This is done
      in prepartion for invoking {@link #setProperty} one or more times.
      
      @param obj  the object for which to set properties
     */
    public
    PropertyGetter(Object obj) throws IntrospectionException {
      BeanInfo bi = Introspector.getBeanInfo(obj.getClass());
      props = bi.getPropertyDescriptors();
      this.obj = obj;
    }
    
    public
    static
    void getProperties(Object obj, PropertyCallback callback, String prefix) {
      try {
        new PropertyGetter(obj).getProperties(callback, prefix);
      } catch (IntrospectionException ex) {
        LogLog.error("Failed to introspect object " + obj, ex);
      }
    }
    
    public
    void getProperties(PropertyCallback callback, String prefix) {
      for (int i = 0; i < props.length; i++) {
          Method getter = props[i].getReadMethod();
          if (getter == null) continue;
          if (!isHandledType(getter.getReturnType())) {
            //System.err.println("Ignoring " + props[i].getName() +" " + getter.getReturnType());
            continue;
          }
          String name = props[i].getName();
          try {
            Object result = getter.invoke(obj, NULL_ARG);
            //System.err.println("PROP " + name +": " + result);
            if (result != null) {
              callback.foundProperty(obj, prefix, name, result);
            }
          } catch (Exception ex) {
            LogLog.warn("Failed to get value of property " + name);
          }
      }
    }
    
    protected
    boolean isHandledType(Class type) {
      return String.class.isAssignableFrom(type) ||
             Integer.TYPE.isAssignableFrom(type) ||
             Long.TYPE.isAssignableFrom(type)    ||
             Boolean.TYPE.isAssignableFrom(type) ||
             Priority.class.isAssignableFrom(type);
    }
  }
  
  
  1.1                  jakarta-log4j/org/apache/log4j/config/PropertyPrinter.java
  
  Index: PropertyPrinter.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software
   * License version 1.1, a copy of which has been included with this
   * distribution in the LICENSE.APL file.
   */
  
  package org.apache.log4j.config;
  
  import java.io.*;
  import java.util.*;
  import org.apache.log4j.*;
  
  /**
     Prints the configuration of the log4j default hierarchy
     (which needs to be auto-initialized) as a propoperties file
     on a {@link PrintWriter}.
     
     @author  Anders Kristensen
   */
  public class PropertyPrinter implements PropertyGetter.PropertyCallback {
    protected int numAppenders = 0;
    protected Hashtable appenderNames = new Hashtable();
    protected Hashtable layoutNames   = new Hashtable();
    protected PrintWriter out;
    protected boolean doCapitalize;
    
    public
    PropertyPrinter(PrintWriter out) {
      this(out, false);
    }
    
    public
    PropertyPrinter(PrintWriter out, boolean doCapitalize) {
      this.out = out;
      this.doCapitalize = doCapitalize;
      
      print(out);
      out.flush();
    }
    
    protected
    String genAppName() {
      return "A" + numAppenders++;
    }
    
    /**
       Returns true if the specified appender name is considered to have
       been generated, i.e. if it is of the form A[0-9]+.
    */
    protected
    boolean isGenAppName(String name) {
      if (name.length() < 2 || name.charAt(0) != 'A') return false;
      
      for (int i = 0; i < name.length(); i++) {
        if (name.charAt(i) < '0' || name.charAt(i) > '9') return false;
      }
      return true;
    }
    
    /**
     * Prints the configuration of the default log4j hierarchy as a Java
     * properties file on the specified Writer.
     * 
     * <p>N.B. print() can be invoked only once!
     */
    public
    void print(PrintWriter out) {
      printOptions(out, Category.getRoot());
      
      Enumeration cats = Category.getCurrentCategories();
      while (cats.hasMoreElements()) {
        printOptions(out, (Category) cats.nextElement());
      }
    }
    
    protected
    void printOptions(PrintWriter out, Category cat) {
      Enumeration appenders = cat.getAllAppenders();
      Priority prio = cat.getPriority();
      String appenderString = (prio == null ? "" : prio.toString());
      
      while (appenders.hasMoreElements()) {
        Appender app = (Appender) appenders.nextElement();
        String name;
        
        if ((name = (String) appenderNames.get(app)) == null) {
        
          // first assign name to the appender
          if ((name = app.getName()) == null || isGenAppName(name)) {
              name = genAppName();
          }
          appenderNames.put(app, name);
          
          printOptions(out, app, "log4j.appender."+name);
          if (app.getLayout() != null) {
            printOptions(out, app.getLayout(), "log4j.appender."+name+".layout");
          }
        }
        appenderString += ", " + name;
      }
      String catKey = (cat == Category.getRoot())
          ? "log4j.rootCategory"
          : "log4j.category." + cat.getName();
      if (appenderString != "") {
        out.println(catKey + "=" + appenderString);
      }
    }
    
    protected
    void printOptions(PrintWriter out, Object obj, String fullname) {
      out.println(fullname + "=" + obj.getClass().getName());
      PropertyGetter.getProperties(obj, this, fullname + ".");
    }
    
    public void foundProperty(Object obj, String prefix, String name, Object value) {
      // XXX: Properties encode value.toString()
      if (obj instanceof Appender && "name".equals(name)) {
        return;
      }
      if (doCapitalize) {
        name = capitalize(name);
      }
      out.println(prefix + name + "=" + value.toString());
    }
    
    public static String capitalize(String name) {
      if (Character.isLowerCase(name.charAt(0))) {
        if (name.length() == 1 || Character.isLowerCase(name.charAt(1))) {
          StringBuffer newname = new StringBuffer(name);
          newname.setCharAt(0, Character.toUpperCase(name.charAt(0)));
          return newname.toString();
        }
      }
      return name;
    }
    
    // for testing
    public static void main(String[] args) {
      new PropertyPrinter(new PrintWriter(System.out));
    }
  }
  
  
  1.1                  jakarta-log4j/org/apache/log4j/config/PropertySetter.java
  
  Index: PropertySetter.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.APL file.
   */
  
  package org.apache.log4j.config;
  
  import java.beans.*;
  import java.io.*;
  import java.lang.reflect.*;
  import java.util.*;
  import org.apache.log4j.*;
  import org.apache.log4j.helpers.LogLog;
  import org.apache.log4j.helpers.OptionConverter;
  import org.apache.log4j.spi.OptionHandler;
  
  /**
     General purpose Object property setter. Clients repeatedly invokes
     {@link #setProperty setProperty(name,value)} in order to invoke setters
     on the Object specified in the constructor. This class relies on the
     JavaBeans {@link Introspector} to analyze the given Object Class using
     reflection.
     
     <p>Usage:
     <pre>
       PropertySetter ps = new PropertySetter(anObject);
       ps.set("name", "Joe");
       ps.set("age", "32");
       ps.set("isMale", "true");
     </pre>
     will cause the invocations anObject.setName("Joe"), anObject.setAge(32),
     and setMale(true) if such methods exist with those signatures.
     Otherwise an {@link IntrospectionException} are thrown.
    
     @author Anders Kristensen
     @since 1.1
   */
  public class PropertySetter {
    protected Object obj;
    protected PropertyDescriptor[] props;
    
    /**
      Create a new PropertySetter for the specified Object. This is done
      in prepartion for invoking {@link #setProperty} one or more times.
      
      @param obj  the object for which to set properties
     */
    public
    PropertySetter(Object obj) {
      this.obj = obj;
    }
    
    /**
       Uses JavaBeans {@link Introspector} to computer setters of object to be
       configured.
     */
    protected
    void introspect() {
      try {
        BeanInfo bi = Introspector.getBeanInfo(obj.getClass());
        props = bi.getPropertyDescriptors();
      } catch (IntrospectionException ex) {
        LogLog.error("Failed to introspect "+obj+": " + ex.getMessage());
        props = new PropertyDescriptor[0];
      }
    }
    
    public
    static
    void setProperties(Object obj, Properties properties, String prefix) {
      new PropertySetter(obj).setProperties(properties, prefix);
    }
    
    // driven by property map
    public
    void setProperties(Properties properties, String prefix) {
      int len = prefix.length();
      
      for (Enumeration e = properties.keys(); e.hasMoreElements(); ) {
        String name = (String) e.nextElement();
        
        if (name.startsWith(prefix)) {
          if (name.indexOf('.', len + 1) > 0) continue;
          
          //String value = properties.getProperty(name);
  	String value = OptionConverter.findAndSubst(name, properties);
          name = name.substring(prefix.length());
          if ("layout".equals(name) && obj instanceof Appender) {
            continue;
          }
          
          setProperty(name, value);
        }
      }
      activate();
    }
    
    /**
       Set a property on this PropertySetter's Object. If successful, this
       method will invoke a setter method on the underlying Object. The
       setter is the one for the specified property name and the value is
       determined partly from the setter argument type and partly from the
       value specified in the call to this method.
       
       <p>If the setter expects a String no conversion is necessary.
       If it expects an int, then an attempt is made to convert 'value'
       to an int using new Integer(value). If the setter expects a boolean,
       the conversion is by new Boolean(value).
       
       @param name    name of the property
       @param value   String value of the property
       @throws PropertySetterException
              if no setter exists for the named property,
              or if the setter takes an unkown argument type, i.e. one
              other than String, int, and boolean,
              or if the setter method isn't public
     */
    public
    void setProperty(String name, String value) {
      if (value == null) return;
      
      name = Introspector.decapitalize(name);
      PropertyDescriptor prop = getPropertyDescriptor(name);
      
      if (prop == null) {
        LogLog.warn("No such property: " + name);
      } else {
        try {
          setProperty(prop, name, value);
        } catch (PropertySetterException ex) {
          LogLog.warn("Failed to set property " + name +
                      " to value \"" + value + "\": " + ex.getMessage());
        }
      }
    }
    
    /*
    public
    void setProperty(String name, String value) throws PropertySetterException {
      if (props == null) introspect();
      name = Introspector.decapitalize(name);
      PropertyDescriptor prop = getPropertyDescriptor(name);
      
      if (prop != null) {
        setProperty(prop, name, value);
      } else {
        throw new PropertySetterException(
            "No such property", obj, name, value);
      }
    }
    */
    
    public
    void setProperty(PropertyDescriptor prop, String name, String value)
      throws PropertySetterException
    {
      Method setter = prop.getWriteMethod();
      if (setter == null) {
        throw new PropertySetterException("No setter for property");
      }
      Class[] paramTypes = setter.getParameterTypes();
      if (paramTypes.length != 1) {
        throw new PropertySetterException("#params for setter != 1");
      }
      
      Object arg;
      try {
        arg = getArg(value, paramTypes[0]);
      } catch (Throwable t) {
        throw new PropertySetterException(t);
      }
      if (arg == null) {
        throw new PropertySetterException(
            "Unknown property type: "+ paramTypes[0]);
      }
      LogLog.debug("Setting property " + name + ": " + arg);
      try {
        setter.invoke(obj, new Object[]  { arg });
      } catch (Exception ex) {
        throw new PropertySetterException(ex);
      }
    }
    
    protected
    Object getArg(String val, Class type) {
      if (String.class.isAssignableFrom(type)) {
        return val;
      } else if (Integer.TYPE.isAssignableFrom(type)) {
        return new Integer(val.trim());
      } else if (Long.TYPE.isAssignableFrom(type)) {
        return new Long(val.trim());
      } else if (Boolean.TYPE.isAssignableFrom(type)) {
        val = val.trim();
        if ("true".equalsIgnoreCase(val)) {
          return Boolean.TRUE;
        } else if ("false".equalsIgnoreCase(val)) {
          return Boolean.FALSE;
        }
      } else if (Priority.class.isAssignableFrom(type)) {
        return Priority.toPriority(val.trim());
      }
      return null;
    }
    
    protected
    PropertyDescriptor getPropertyDescriptor(String name) {
      if (props == null) introspect();
      
      for (int i = 0; i < props.length; i++) {
        if (name.equals(props[i].getName())) return props[i];
      }
      return null;
    }
    
    public
    void activate() {
      if (obj instanceof OptionHandler) {
          ((OptionHandler) obj).activateOptions();
      }
    }
  }
  
  
  
  1.1                  jakarta-log4j/org/apache/log4j/config/PropertySetterException.java
  
  Index: PropertySetterException.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE.APL file.
   */
  
  package org.apache.log4j.config;
  
  /**
   * Thrown when an error is encountered whilst attempting to set a property
   * using the {@link PropertySetter} utility class.
   * 
   * @author Anders Kristensen
   * @since 1.1
   */
  public class PropertySetterException extends Exception {
    protected Throwable rootCause;
    
    public
    PropertySetterException(String msg) {
      super(msg);
    }
    
    public
    PropertySetterException(Throwable rootCause)
    {
      super();
      this.rootCause = rootCause;
    }
    
    /**
       Returns descriptive text on the cause of this exception.
     */
    public
    String getMessage() {
      String msg = super.getMessage();
      if (msg == null && rootCause != null) {
        msg = rootCause.getMessage();
      }
      return msg;
    }
  }
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-cvs-unsubscribe@jakarta.apache.org
For additional commands, e-mail: log4j-cvs-help@jakarta.apache.org