JAL-3541 selectively merged build.gradle and gradle.properties
[jalview.git] / srcjar_unused / org / apache / log4j / config / PropertySetter.java
diff --git a/srcjar_unused/org/apache/log4j/config/PropertySetter.java b/srcjar_unused/org/apache/log4j/config/PropertySetter.java
new file mode 100644 (file)
index 0000000..dae3c00
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ */
+
+// Contributors:  Georg Lundesgaard
+
+package org.apache.log4j.config;
+
+import org.apache.log4j.Appender;
+import org.apache.log4j.Level;
+import org.apache.log4j.Priority;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.helpers.OptionConverter;
+import org.apache.log4j.spi.OptionHandler;
+import org.apache.log4j.spi.ErrorHandler;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.InterruptedIOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+import java.util.Properties;
+
+/**
+   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];
+    }
+  }
+  
+
+  /**
+     Set the properties of an object passed as a parameter in one
+     go. The <code>properties</code> are parsed relative to a
+     <code>prefix</code>.
+
+     @param obj The object to configure.
+     @param properties A java.util.Properties containing keys and values.
+     @param prefix Only keys having the specified prefix will be set.
+  */
+  public
+  static
+  void setProperties(Object obj, Properties properties, String prefix) {
+    new PropertySetter(obj).setProperties(properties, prefix);
+  }
+  
+
+  /**
+     Set the properites for the object that match the
+     <code>prefix</code> passed as parameter.
+
+     
+   */
+  public
+  void setProperties(Properties properties, String prefix) {
+    int len = prefix.length();
+    
+    for (Enumeration e = properties.propertyNames(); e.hasMoreElements(); ) {
+      String key = (String) e.nextElement();
+      
+      // handle only properties that start with the desired frefix.
+      if (key.startsWith(prefix)) {
+
+       
+       // ignore key if it contains dots after the prefix
+        if (key.indexOf('.', len + 1) > 0) {
+         //System.err.println("----------Ignoring---["+key
+         //         +"], prefix=["+prefix+"].");
+         continue;
+       }
+        
+       String value = OptionConverter.findAndSubst(key, properties);
+        key = key.substring(len);
+        if (("layout".equals(key) || "errorhandler".equals(key)) && obj instanceof Appender) {
+          continue;
+        }
+        //
+        //   if the property type is an OptionHandler
+        //     (for example, triggeringPolicy of org.apache.log4j.rolling.RollingFileAppender)
+        PropertyDescriptor prop = getPropertyDescriptor(Introspector.decapitalize(key));
+        if (prop != null
+                && OptionHandler.class.isAssignableFrom(prop.getPropertyType())
+                && prop.getWriteMethod() != null) {
+            OptionHandler opt = (OptionHandler)
+                    OptionConverter.instantiateByKey(properties, prefix + key,
+                                  prop.getPropertyType(),
+                                  null);
+            PropertySetter setter = new PropertySetter(opt);
+            setter.setProperties(properties, prefix + key + ".");
+            try {
+                prop.getWriteMethod().invoke(this.obj, new Object[] { opt });
+            } catch(IllegalAccessException ex) {
+                LogLog.warn("Failed to set property [" + key +
+                            "] to value \"" + value + "\". ", ex);
+            } catch(InvocationTargetException ex) {
+                if (ex.getTargetException() instanceof InterruptedException
+                        || ex.getTargetException() instanceof InterruptedIOException) {
+                    Thread.currentThread().interrupt();
+                }
+                LogLog.warn("Failed to set property [" + key +
+                            "] to value \"" + value + "\". ", ex);
+            } catch(RuntimeException ex) {
+                LogLog.warn("Failed to set property [" + key +
+                            "] to value \"" + value + "\". ", ex);
+            }
+            continue;
+        }
+
+        setProperty(key, 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
+   */
+  public
+  void setProperty(String name, String value) {
+    if (value == null) {
+        return;
+    }
+    
+    name = Introspector.decapitalize(name);
+    PropertyDescriptor prop = getPropertyDescriptor(name);
+    
+    //LogLog.debug("---------Key: "+name+", type="+prop.getPropertyType());
+
+    if (prop == null) {
+      LogLog.warn("No such property [" + name + "] in "+
+                 obj.getClass().getName()+"." );
+    } else {
+      try {
+        setProperty(prop, name, value);
+      } catch (PropertySetterException ex) {
+        LogLog.warn("Failed to set property [" + name +
+                    "] to value \"" + value + "\". ", ex.rootCause);
+      }
+    }
+  }
+  
+  /** 
+      Set the named property given a {@link PropertyDescriptor}.
+
+      @param prop A PropertyDescriptor describing the characteristics
+      of the property to set.
+      @param name The named of the property to set.
+      @param value The value of the property.      
+   */
+  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 ["+name+"].");
+    }
+    Class[] paramTypes = setter.getParameterTypes();
+    if (paramTypes.length != 1) {
+      throw new PropertySetterException("#params for setter != 1");
+    }
+    
+    Object arg;
+    try {
+      arg = convertArg(value, paramTypes[0]);
+    } catch (Throwable t) {
+      throw new PropertySetterException("Conversion to type ["+paramTypes[0]+
+                                       "] failed. Reason: "+t);
+    }
+    if (arg == null) {
+      throw new PropertySetterException(
+          "Conversion to type ["+paramTypes[0]+"] failed.");
+    }
+    LogLog.debug("Setting property [" + name + "] to [" +arg+"].");
+    try {
+      setter.invoke(obj, new Object[]  { arg });
+    } catch (IllegalAccessException ex) {
+      throw new PropertySetterException(ex);
+    } catch (InvocationTargetException ex) {
+        if (ex.getTargetException() instanceof InterruptedException
+                || ex.getTargetException() instanceof InterruptedIOException) {
+            Thread.currentThread().interrupt();
+        }        
+        throw new PropertySetterException(ex);
+    } catch (RuntimeException ex) {
+      throw new PropertySetterException(ex);
+    }
+  }
+  
+
+  /**
+     Convert <code>val</code> a String parameter to an object of a
+     given type.
+  */
+  protected
+  Object convertArg(String val, Class type) {
+    if(val == null) {
+        return null;
+    }
+
+    String v = val.trim();
+    if (String.class.isAssignableFrom(type)) {
+      return val;
+    } else if (Integer.TYPE.isAssignableFrom(type)) {
+      return new Integer(v);
+    } else if (Long.TYPE.isAssignableFrom(type)) {
+      return new Long(v);
+    } else if (Boolean.TYPE.isAssignableFrom(type)) {
+      if ("true".equalsIgnoreCase(v)) {
+        return Boolean.TRUE;
+      } else if ("false".equalsIgnoreCase(v)) {
+        return Boolean.FALSE;
+      }
+    } else if (Priority.class.isAssignableFrom(type)) {
+      return OptionConverter.toLevel(v, Level.DEBUG);
+    } else if (ErrorHandler.class.isAssignableFrom(type)) {
+      return OptionConverter.instantiateByClassName(v, 
+         ErrorHandler.class, null);
+    }
+    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();
+    }
+  }
+}