Author: costin
Date: Thu Nov 26 06:50:10 2009
New Revision: 884419

URL: http://svn.apache.org/viewvc?rev=884419&view=rev
Log:
Few change to the ObjectManager ( intended for integration with existing 
frameworks ).
The 'sample/if no other framework around' SimpleObject manager no longer 
depends on IntrospectionUtils, refactored it ( and parts of modeler )
to DynamicObject. 


Added:
    
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/DynamicObject.java
   (with props)
    
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/AntProperties.java
   (with props)
Removed:
    
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/LocalFilesystem.java
Modified:
    
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/ObjectManager.java
    
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/Main.java
    
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/SimpleObjectManager.java

Added: 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/DynamicObject.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/DynamicObject.java?rev=884419&view=auto
==============================================================================
--- 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/DynamicObject.java
 (added)
+++ 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/DynamicObject.java
 Thu Nov 26 06:50:10 2009
@@ -0,0 +1,393 @@
+/*
+ */
+package org.apache.tomcat.integration;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Refactoring of IntrospectionUtils and modeler dynamic bean.
+ * 
+ * Unlike IntrospectionUtils, the method informations can be cached.
+ * Also I hope this class will be simpler to use. 
+ * There is no static cache.
+ * 
+ * @author Costin Manolache
+ */
+public class DynamicObject {
+    // Based on MbeansDescriptorsIntrospectionSource
+
+    static Logger log = Logger.getLogger(DynamicObject.class.getName());
+
+    static Class<?> NO_PARAMS[] = new Class[0];
+
+
+    private static String strArray[] = new String[0];
+
+    private static Class<?>[] supportedTypes = new Class[] { Boolean.class,
+            Boolean.TYPE, Byte.class, Byte.TYPE, Character.class,
+            Character.TYPE, Short.class, Short.TYPE, Integer.class,
+            Integer.TYPE, Long.class, Long.TYPE, Float.class, Float.TYPE,
+            Double.class, Double.TYPE, String.class, strArray.getClass(),
+            BigDecimal.class, BigInteger.class, AtomicInteger.class,
+            AtomicLong.class, java.io.File.class, };
+
+    
+    private Class realClass;
+
+    private Map<String, Method> getAttMap;
+
+    public DynamicObject(Class beanClass) {
+        this.realClass = beanClass;
+        initCache();
+    }
+
+    public DynamicObject(Class beanClass, boolean noCache) {
+        this.realClass = beanClass;
+    }
+
+    private void initCache() {
+        Method methods[] = null;
+
+        getAttMap = new HashMap<String, Method>();
+
+        methods = realClass.getMethods();
+        for (int j = 0; j < methods.length; ++j) {
+            if (ignorable(methods[j])) {
+                continue;
+            }
+            String name = methods[j].getName();
+
+            Class<?> params[] = methods[j].getParameterTypes();
+
+            if (name.startsWith("get") && params.length == 0) {
+                Class<?> ret = methods[j].getReturnType();
+                if (!supportedType(ret)) {
+                    if (log.isLoggable(Level.FINE))
+                        log.fine("Unsupported type " + methods[j]);
+                    continue;
+                }
+                name = unCapitalize(name.substring(3));
+
+                getAttMap.put(name, methods[j]);
+            } else if (name.startsWith("is") && params.length == 0) {
+                Class<?> ret = methods[j].getReturnType();
+                if (Boolean.TYPE != ret) {
+                    if (log.isLoggable(Level.FINE))
+                        log.fine("Unsupported type " + methods[j] + " " + ret);
+                    continue;
+                }
+                name = unCapitalize(name.substring(2));
+
+                getAttMap.put(name, methods[j]);
+            }
+        }
+    }
+
+    private boolean ignorable(Method method) {
+        if (Modifier.isStatic(method.getModifiers()))
+            return true;
+        if (!Modifier.isPublic(method.getModifiers())) {
+            return true;
+        }
+        if (method.getDeclaringClass() == Object.class)
+            return true;
+        return false;
+    }
+    
+    public List<String> attributeNames() {
+        List<String> attributes = new ArrayList<String>();
+        Method methods[] = realClass.getMethods();
+        for (int j = 0; j < methods.length; ++j) {
+            String name = methods[j].getName();
+            if (ignorable(methods[j])) {
+                continue;
+            }
+            Class<?> params[] = methods[j].getParameterTypes();
+            if (name.startsWith("get") && params.length == 0) {
+                Class<?> ret = methods[j].getReturnType();
+                if (!supportedType(ret)) {
+                    continue;
+                }
+                name = unCapitalize(name.substring(3));
+                attributes.add(name);
+            } else if (name.startsWith("is") && params.length == 0) {
+                Class<?> ret = methods[j].getReturnType();
+                if (Boolean.TYPE != ret) {
+                    continue;
+                }
+                name = unCapitalize(name.substring(2));
+                attributes.add(name);
+            } else if (name.startsWith("set") && params.length == 1) {
+                if (!supportedType(params[0])) {
+                    continue;
+                }
+                name = unCapitalize(name.substring(3));
+                attributes.add(name);
+            }
+        }
+
+        return attributes;
+    }
+
+
+    public Object invoke(Object proxy, String method) throws Exception {
+        Method executeM = null;
+        Class<?> c = proxy.getClass();
+        executeM = c.getMethod(method, NO_PARAMS);
+        if (executeM == null) {
+            throw new RuntimeException("No execute in " + proxy.getClass());
+        }
+        return executeM.invoke(proxy, (Object[]) null);
+    }
+
+    // TODO
+    public Object invoke(String method, Object[] params) {
+        return null;
+    }
+
+    public boolean hasHook(String method) {
+        return false;
+    }
+
+    public Object getAttribute(Object o, String att) {
+        Method m = getAttMap.get(att);
+        if (m == null)
+            return null;
+        try {
+            return m.invoke(o);
+        } catch (Throwable e) {
+            log.log(Level.INFO, "Error getting attribute " + realClass + " "
+                    + att, e);
+            return null;
+        }
+    }
+
+    public boolean setAttribute(Object proxy, String name, Object value) {
+        String methodName = "set" + capitalize(name);
+        Method[] methods = proxy.getClass().getMethods();
+        for (Method m : methods) {
+            Class<?>[] paramT = m.getParameterTypes();
+            if (methodName.equals(m.getName())
+                    && paramT.length == 1
+                    && (value == null || paramT[0].isAssignableFrom(value
+                            .getClass()))) {
+                try {
+                    m.invoke(proxy, value);
+                    return true;
+                } catch (IllegalArgumentException e) {
+                    log.severe("Error setting: " + name + " "
+                            + proxy.getClass().getName() + " " + e);
+                } catch (IllegalAccessException e) {
+                    log.severe("Error setting: " + name + " "
+                            + proxy.getClass().getName() + " " + e);
+                } catch (InvocationTargetException e) {
+                    log.severe("Error setting: " + name + " "
+                            + proxy.getClass().getName() + " " + e);
+                }
+            }
+        }
+        return false;
+    }
+
+    public boolean setProperty(Object proxy, String name, String value) {
+        String setter = "set" + capitalize(name);
+
+        try {
+            Method methods[] = proxy.getClass().getMethods();
+            
+            Method setPropertyMethod = null;
+
+            // First, the ideal case - a setFoo( String ) method
+            for (int i = 0; i < methods.length; i++) {
+                if (ignorable(methods[i])) {
+                    continue;
+                }
+                Class<?> paramT[] = methods[i].getParameterTypes();
+                if (setter.equals(methods[i].getName()) && paramT.length == 1) 
{
+                    if ("java.lang.String".equals(paramT[0].getName())) {
+                        methods[i].invoke(proxy, new Object[] { value });
+                        return true;
+                    } else {
+                        // match - find the type and invoke it
+                        Class<?> paramType = methods[i].getParameterTypes()[0];
+                        Object params[] = new Object[1];
+                        params[0] = convert(value, paramType);
+                        if (params[0] != null) {
+                            methods[i].invoke(proxy, params);
+                            return true;
+                        }
+                    }
+                }
+                // save "setProperty" for later
+                if ("setProperty".equals(methods[i].getName()) && 
+                        paramT.length == 2 &&
+                        paramT[0] == String.class &&
+                        paramT[1] == String.class) {
+                    setPropertyMethod = methods[i];
+                }
+            }
+
+            try {
+                Field field = proxy.getClass().getField(name);
+                if (field != null) {
+                    Object conv = convert(value, field.getType());
+                    if (conv != null) {
+                        field.set(proxy, conv);
+                        return true;
+                    }
+                }
+            } catch (NoSuchFieldException e) {
+                // ignore
+            }
+
+            // Ok, no setXXX found, try a setProperty("name", "value")
+            if (setPropertyMethod != null) {
+                Object params[] = new Object[2];
+                params[0] = name;
+                params[1] = value;
+                setPropertyMethod.invoke(proxy, params);
+                return true;
+            }
+
+        } catch (Throwable ex2) {
+            log.log(Level.WARNING, "IAE " + proxy + " " + name + " " + value,
+                    ex2);
+        }
+        return false;
+    }
+
+    // ----------- Helpers ------------------
+    
+    static Object convert(String object, Class<?> paramType) {
+        Object result = null;
+        if ("java.lang.String".equals(paramType.getName())) {
+            result = object;
+        } else if ("java.lang.Long".equals(paramType.getName())
+                || "long".equals(paramType.getName())) {
+            try {
+                result = Long.parseLong(object);
+            } catch (NumberFormatException ex) {
+            }
+            // Try a setFoo ( boolean )
+        } else if ("java.lang.Integer".equals(paramType.getName())
+                || "int".equals(paramType.getName())) {
+            try {
+                result = new Integer(object);
+            } catch (NumberFormatException ex) {
+            }
+            // Try a setFoo ( boolean )
+        } else if ("java.lang.Boolean".equals(paramType.getName())
+                || "boolean".equals(paramType.getName())) {
+            result = new Boolean(object);
+        } else {
+            log.info("Unknown type " + paramType.getName());
+        }
+        if (result == null) {
+            throw new IllegalArgumentException("Can't convert argument: "
+                    + object +  " to " + paramType );
+        }
+        return result;
+    }
+
+    /**
+     * Converts the first character of the given String into lower-case.
+     * 
+     * @param name
+     *            The string to convert
+     * @return String
+     */
+    static String unCapitalize(String name) {
+        if (name == null || name.length() == 0) {
+            return name;
+        }
+        char chars[] = name.toCharArray();
+        chars[0] = Character.toLowerCase(chars[0]);
+        return new String(chars);
+    }
+
+    /**
+     * Check if this class is one of the supported types. If the class is
+     * supported, returns true. Otherwise, returns false.
+     * 
+     * @param ret
+     *            The class to check
+     * @return boolean True if class is supported
+     */
+    static boolean supportedType(Class<?> ret) {
+        for (int i = 0; i < supportedTypes.length; i++) {
+            if (ret == supportedTypes[i]) {
+                return true;
+            }
+        }
+        if (isBeanCompatible(ret)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Check if this class conforms to JavaBeans specifications. If the class 
is
+     * conformant, returns true.
+     * 
+     * @param javaType
+     *            The class to check
+     * @return boolean True if the class is compatible.
+     */
+    static boolean isBeanCompatible(Class<?> javaType) {
+        // Must be a non-primitive and non array
+        if (javaType.isArray() || javaType.isPrimitive()) {
+            return false;
+        }
+
+        // Anything in the java or javax package that
+        // does not have a defined mapping is excluded.
+        if (javaType.getName().startsWith("java.")
+                || javaType.getName().startsWith("javax.")) {
+            return false;
+        }
+
+        try {
+            javaType.getConstructor(new Class[] {});
+        } catch (java.lang.NoSuchMethodException e) {
+            return false;
+        }
+
+        // Make sure superclass is compatible
+        Class<?> superClass = javaType.getSuperclass();
+        if (superClass != null && superClass != java.lang.Object.class
+                && superClass != java.lang.Exception.class
+                && superClass != java.lang.Throwable.class) {
+            if (!isBeanCompatible(superClass)) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    /**
+     * Reverse of Introspector.decapitalize
+     */
+    static String capitalize(String name) {
+        if (name == null || name.length() == 0) {
+            return name;
+        }
+        char chars[] = name.toCharArray();
+        chars[0] = Character.toUpperCase(chars[0]);
+        return new String(chars);
+    }
+
+    
+}

Propchange: 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/DynamicObject.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/ObjectManager.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/ObjectManager.java?rev=884419&r1=884418&r2=884419&view=diff
==============================================================================
--- 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/ObjectManager.java
 (original)
+++ 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/ObjectManager.java
 Thu Nov 26 06:50:10 2009
@@ -79,6 +79,19 @@
     }
 
     /**
+     * Create or get a new object with the given name.
+     */
+    public String getProperty(String key) {
+        for (ObjectManager p : children) {
+            String o = p.getProperty(key);
+            if (o != null) {
+                return o;
+            }
+        }        
+        return null;
+    }
+
+    /**
      * Helper for typed get.
      */
     public Object get(Class c) {
@@ -93,6 +106,6 @@
         new ArrayList<ObjectManager>(); 
     
     public void register(ObjectManager om) {
-        om.children.add(this);
+        children.add(om);
     }    
 }

Added: 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/AntProperties.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/AntProperties.java?rev=884419&view=auto
==============================================================================
--- 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/AntProperties.java
 (added)
+++ 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/AntProperties.java
 Thu Nov 26 06:50:10 2009
@@ -0,0 +1,75 @@
+/*
+ */
+package org.apache.tomcat.integration.simple;
+
+import java.util.Hashtable;
+
+/**
+ * Extracted from IntrospectionHelper - a simple utility class to 
+ * do ant style ${property} replacements on a string, using a map
+ * holding properties. Also allows a hook for dynamic, on-demand 
+ * properties.
+ * 
+ * @author Costin Manolache
+ */
+public class AntProperties {
+    public static interface PropertySource {
+        public String getProperty(String key);
+    }
+
+    /**
+     * Replace ${NAME} with the property value
+     */
+    public static String replaceProperties(String value,
+            Hashtable<Object,Object> staticProp, PropertySource dynamicProp[]) 
{
+        if (value.indexOf("$") < 0) {
+            return value;
+        }
+        StringBuffer sb = new StringBuffer();
+        int prev = 0;
+        // assert value!=nil
+        int pos;
+        while ((pos = value.indexOf("$", prev)) >= 0) {
+            if (pos > 0) {
+                sb.append(value.substring(prev, pos));
+            }
+            if (pos == (value.length() - 1)) {
+                sb.append('$');
+                prev = pos + 1;
+            } else if (value.charAt(pos + 1) != '{') {
+                sb.append('$');
+                prev = pos + 1; // XXX
+            } else {
+                int endName = value.indexOf('}', pos);
+                if (endName < 0) {
+                    sb.append(value.substring(pos));
+                    prev = value.length();
+                    continue;
+                }
+                String n = value.substring(pos + 2, endName);
+                String v = null;
+                if (staticProp != null) {
+                    v = (String) staticProp.get(n);
+                }
+                if (v == null && dynamicProp != null) {
+                    for (int i = 0; i < dynamicProp.length; i++) {
+                        v = dynamicProp[i].getProperty(n);
+                        if (v != null) {
+                            break;
+                        }
+                    }
+                }
+                if (v == null)
+                    v = "${" + n + "}";
+
+                sb.append(v);
+                prev = endName + 1;
+            }
+        }
+        if (prev < value.length())
+            sb.append(value.substring(prev));
+        return sb.toString();
+    }
+
+
+}

Propchange: 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/AntProperties.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/Main.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/Main.java?rev=884419&r1=884418&r2=884419&view=diff
==============================================================================
--- 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/Main.java
 (original)
+++ 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/Main.java
 Thu Nov 26 06:50:10 2009
@@ -17,7 +17,6 @@
 
 package org.apache.tomcat.integration.simple;
 
-import org.apache.tomcat.integration.ObjectManager;
 
 /**
  * Replacement for tomcat-lite specific Main, using the simple 
@@ -28,17 +27,34 @@
  * @author Costin Manolache
  */
 public class Main {
+    static boolean running = true;
+    static Object lock = new Object();
+    
+    public static void stop() {
+        running = false;
+        synchronized (lock) {
+            lock.notify();
+        }
+    }
+    
+    public static void waitStop() {
+        while (running) {
+            try {
+                synchronized (lock) {
+                    lock.wait();
+                }
+            } catch (InterruptedException e) {
+            }
+        }
+    }
 
     public static void main(String args[]) 
-    throws Exception {
-        SimpleObjectManager om = new SimpleObjectManager();
-        
-        // Will process CLI. 
-        // 'config' will load a config file.
-        om.bind("Main.args", args);
+            throws Exception {
+        // '--config' will load a config file.
+        SimpleObjectManager om = new SimpleObjectManager(args);
 
-        Runnable main = (Runnable) om.get("Main");
-        if (main == null) {
+        String run = (String) om.getProperty("RUN");
+        if (run == null) {
             // TODO: look for a pre-defined name in local dir, resource,
             // manifest
             System.err.println("Using default tomcat-lite configuration");
@@ -50,16 +66,16 @@
             
             String cfgFile = "org/apache/tomcat/lite/config.properties";
             om.loadResource(cfgFile);
-            main = (Runnable) om.get("Main");
+            run = (String) om.getProperty("RUN");
         }
         
-        // add JMX support
-        ObjectManager jmx = (ObjectManager) om.get("JMX");
-        if (jmx != null) {
-            jmx.register(om);
+        String[] runNames = run.split(",");
+        for (String name: runNames) {
+            Object main = om.get(name);
+            if (main instanceof Runnable) {
+                ((Runnable) main).run();
+            }
         }
-
-        main.run();
-
+        
     }    
 }

Modified: 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/SimpleObjectManager.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/SimpleObjectManager.java?rev=884419&r1=884418&r2=884419&view=diff
==============================================================================
--- 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/SimpleObjectManager.java
 (original)
+++ 
tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/SimpleObjectManager.java
 Thu Nov 26 06:50:10 2009
@@ -24,111 +24,162 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.apache.tomcat.integration.DynamicObject;
 import org.apache.tomcat.integration.ObjectManager;
-import org.apache.tomcat.util.IntrospectionUtils;
 
 /**
- * This is a very small 'dependency injection'/registry poor-man substitute,
+ * This is a very small 'dependency injection'/registry poor-man substitute, 
  * based on old tomcat IntrospectionUtils ( which is based on ant ).
  * Alternative would be to just pick one of spring/guice/etc and use it.
  * This class is a bit smaller and should be enough for simple use.
- *
- * How it works:
+ * 
+ * How it works: 
  *  - when bound, simple properties are injected in the objects using
  *  the old IntrospectionUtils, same as in original Tomcat server.xml
- *
+ *   
  *  - object creation using class name - properties injected as well.
  *  Similar with how server.xml or ant works.
- *
- *  - it is based on a big Properties file, with command line arguments
+ *  
+ *  - it is based on a big Properties file, with command line arguments 
  *  merged in.
- *
+ *  
  * Tomcat doesn't require any of the features - they are just used to
- * allow configuration in 'default' mode, when no other framework is
- * used.
- *
+ * allow configuration in 'default' mode, when no other framework is 
+ * used.  
+ * 
  * See the Spring example for an alternative. I believe most POJO frameworks
- * can be supported.
- *
+ * can be supported. 
+ * 
  * @author Costin Manolache
  */
 public class SimpleObjectManager extends ObjectManager {
-    static Logger log = Logger.getLogger(SimpleObjectManager.class.getName());
+    public static final String ARGS = "Main.args";
 
+    static Logger log = Logger.getLogger(SimpleObjectManager.class.getName());
+    
     protected Properties props = new Properties();
     protected Map<String, Object> objects = new HashMap();
-    ObjectManager om;
-
+    
     public SimpleObjectManager() {
         // Register PropertiesSpi
     }
 
     public SimpleObjectManager(String[] args) {
         this();
-        bind("Main.args", args);
+        bind(ARGS, args);
     }
-
+    
     public void loadResource(String res) {
         InputStream in = this.getClass().getClassLoader()
             .getResourceAsStream(res);
-        load(in);
+        if (in != null) {
+            load(in);
+        }
     }
-
+    
     public void register(ObjectManager om) {
-        this.om = om;
         super.register(om);
     }
-
+    
     public ObjectManager getObjectManager() {
-        return om;
+        return this;
     }
 
     public void load(InputStream is) {
         try {
             props.load(is);
+            processIncludes();
         } catch (IOException e) {
             throw new RuntimeException("Error loading default config");
         }
     }
-
+    
+    // resolve included "config". Very basic, just one, etc.
+    private void processIncludes() throws IOException {
+        String value = props.getProperty("config");
+        if (value == null) {
+            value = props.getProperty("include");
+            if (value != null) {
+                props.remove("include");
+            }
+        } else {
+            // avoid loop
+            props.remove("config");
+        }
+        if (value == null) {
+            return;
+        }
+        if (new File(value).exists()) {
+            load(new FileInputStream(value));                    
+        } else {
+            loadResource(value);
+        }
+    }
+    
     public Properties getProperties() {
         return props;
     }
-
+    
     @Override
     public void unbind(String name) {
+        // Children
+        // TODO: call @destroy
+        super.unbind(name);
     }
 
     @Override
     public void bind(String name, Object o) {
         //log.info("Bound: " + name + " " + o);
 
-        if ("Main.args".equals(name)) {
+        if (ARGS.equals(name)) {
             try {
                 processArgs((String[]) o, props);
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
         }
-
-        // TODO: can I make 'inject' public - Guice seems to
+        
+        // TODO: can I make 'inject' public - Guice seems to 
         // support this.
         inject(name, o);
+        
+        // Children
+        super.bind(name, o);
     }
 
     @Override
     public Object get(String key) {
         // Use same syntax as Spring props.
+        Object res = null;
         String prop = props.getProperty(key + ".(class)");
         if (prop != null) {
-            Object res = loadClass(prop);
-            inject(key, res);
-            return res;
+            res = loadClass(prop);
         }
 
-        return null;
+        if (res == null) {
+            res = super.get(key);
+        }
+        
+        if (res == null) {
+            // Maybe it's just a class name
+            res = loadClass(key);
+        }
+        
+        if (res != null) {
+            inject(key, res);
+        }
+        return res;
+    }
+    
+    public String getProperty(String key) {
+        String prop = props.getProperty(key);
+        if (prop != null) {
+            return prop;
+        }
+        return super.getProperty(key);
     }
 
     private void inject(String name, Object o) {
@@ -136,13 +187,18 @@
         String pref = name + ".";
         int prefLen = pref.length();
 
-        for (String k: props.stringPropertyNames()) {
+        DynamicObject dyno = new DynamicObject(o.getClass());
+        dyno.setAttribute(o, "ObjectManager", this);
+
+        for (Object kObj: props.keySet()) {
+            if (!(kObj instanceof String)) {continue;}
+            String k = (String) kObj;
             if (k.startsWith(pref)) {
                 if (k.endsWith(")")) {
-                    continue; // special
+                    continue; // special 
                 }
                 String value = props.getProperty(k);
-                value = IntrospectionUtils.replaceProperties(value,
+                value = AntProperties.replaceProperties(value, 
                         props, null);
                 String p = k.substring(prefLen);
                 int idx = p.indexOf(".");
@@ -150,38 +206,45 @@
                     // ignore suffix - indexed properties
                     p = p.substring(0, idx);
                 }
-                IntrospectionUtils.setProperty(o, p, value);
-                log.info("Setting: " + name + " " + k + " " + value);
+                dyno.setProperty(o, p, value);
+                if (log.isLoggable(Level.FINE)) {
+                    log.info("Setting: " + name + " " + k + " " + value);
+                }
             }
         }
+        
+
         // We could do cooler things - inject objects, etc.
     }
-
+    
+    
     private Object loadClass(String className) {
         try {
             Class c = Class.forName(className);
+            if (c.isInterface()) {
+                return null;
+            }
             Object ext = c.newInstance();
             return ext;
         } catch (Throwable e) {
-            e.printStackTrace();
             return null;
-        }
+        }        
     }
-
+    
     /**
      * Populate properties based on CLI:
      *  -key value
      *  --key=value
-     *
+     *  
      *  --config=FILE - load a properties file
-     *
+     *  
      * @param args
      * @param p
      * @param meta
      * @return everything after the first non arg not starting with '-'
-     * @throws IOException
+     * @throws IOException 
      */
-    public String[] processArgs(String[] args, Properties props)
+    public String[] processArgs(String[] args, Properties props) 
             throws IOException {
 
         for (int i = 0; i < args.length; i++) {
@@ -193,10 +256,11 @@
             } else {
                 String [] res = new String[args.length - i];
                 System.arraycopy(args, i, res, 0, res.length);
+                processIncludes();
                 return res;
             }
-
-            String name = arg;
+            
+            String name = arg; 
             int eq = arg.indexOf("=");
             String value = null;
             if (eq > 0) {
@@ -210,16 +274,11 @@
                 value = args[i];
             }
 
-            if ("config".equals(arg)) {
-                if (new File(value).exists()) {
-                    load(new FileInputStream(value));
-                } else {
-                    loadResource(value);
-                }
-            } else {
-                props.put(name, value);
-            }
+            props.put(name, value);
+            
         }
+        
+        processIncludes();
         return new String[] {};
-    }
+    }    
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to