You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by jo...@apache.org on 2012/09/26 12:04:14 UTC

svn commit: r1390365 [2/2] - in /commons/sandbox/jndi/trunk/commons-jndi: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/commons/ src/main/java/org/apache/commons/jndi/ src/main/java/org/apache/co...

Added: commons/sandbox/jndi/trunk/commons-jndi/src/main/java/org/apache/commons/jndi/util/Reflection.java
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/main/java/org/apache/commons/jndi/util/Reflection.java?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/main/java/org/apache/commons/jndi/util/Reflection.java (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/main/java/org/apache/commons/jndi/util/Reflection.java Wed Sep 26 10:04:12 2012
@@ -0,0 +1,445 @@
+/*
+ * 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.commons.jndi.util;
+
+import java.io.File;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.naming.NamingException;
+
+
+/**
+ * Utility class for working with reflection.
+ */
+public class Reflection {
+    private static final Class<?>[] ZERO_CLASSES = new Class<?>[0];
+    private static final Object[] ZERO_OBJECTS = new Object[0];
+
+    /**
+     * Private constructor, to prevent accidental instantiation.
+     */
+    private Reflection() {
+        // Nothing to do
+    }
+
+    /**
+     * Returns a getter for the given property on instances of
+     * the given class.
+     */
+    public static Method getGetter(Class<?> pClass, String pProperty) throws NoSuchMethodException {
+        if (pProperty.length() > 0) {
+            Method m = null;
+            final String suffix = Character.toUpperCase(pProperty.charAt(0)) + pProperty.substring(1);
+            try {
+                m = pClass.getMethod("get" + suffix, ZERO_CLASSES);
+            } catch (NoSuchMethodException e) {
+                // Ignore me.
+            }
+            if (m == null) {
+                try {
+                    m = pClass.getMethod("is" + suffix, ZERO_CLASSES);
+                    if (!boolean.class.equals(m.getReturnType())) {
+                        m = null;
+                    }
+                } catch (NoSuchMethodException e2) {
+                    // Ignore me.
+                }
+                if (m == null) {
+                    try {
+                        m = pClass.getMethod("has" + suffix, ZERO_CLASSES);
+                        if (!boolean.class.equals(m.getReturnType())) {
+                            m = null;
+                        }
+                    } catch (NoSuchMethodException e2) {
+                        // Ignore me.
+                    }
+                }
+            }
+            if (m != null) {
+                final int modifier = m.getModifiers();
+                if (!Modifier.isStatic(modifier)
+                    &&  !Modifier.isAbstract(modifier)
+                    &&  !void.class.equals(m.getReturnType())) {
+                    return m;
+                }
+            }
+        }
+        throw new NoSuchMethodException("No getter found for property " + pProperty
+                + " of class " + pClass.getName());
+    }
+
+    /**
+     * Returns a setter for the given property on instances of
+     * the given class.
+     */
+    public static Method getSetter(Class<?> pClass, String pProperty) throws NoSuchMethodException {
+        for (Method m : pClass.getMethods()) {
+            final String name = m.getName();
+            final int modifier = m.getModifiers();
+            if (!Modifier.isAbstract(modifier)
+                    &&  Modifier.isPublic(modifier)
+                    &&  !Strings.isEmpty(pProperty)
+                    &&  name.length() == pProperty.length()+3
+                    &&  name.startsWith("set")
+                    &&  Character.toUpperCase(name.charAt("set".length())) == Character.toUpperCase(pProperty.charAt(0))
+                    &&  name.substring("set".length()+1).equals(pProperty.substring(1))
+                    &&  void.class.equals(m.getReturnType())) {
+                final Class<?>[] paramTypes = m.getParameterTypes();
+                if (paramTypes != null  &&  paramTypes.length == 1) {
+                    return m;
+                }
+            }
+        }
+        throw new NoSuchMethodException("No setter found for property " + pProperty
+                + " in class " + pClass.getCanonicalName());
+    }
+
+    /**
+     * Converts the given value into an instance of the given class.
+     */
+    public static Object getValue(Class<?> pClass, String pValue) {
+        if (pValue == null) {
+            if (pClass.isPrimitive()) {
+                throw new IllegalArgumentException("Invalid value for primitive class "
+                        + pClass.getCanonicalName() + ": null");
+            }
+            return null;
+        }
+        if (String.class.equals(pClass)) {
+            return pValue;
+        } else if (boolean.class.equals(pClass)  ||  Boolean.class.equals(pClass)) {
+            try {
+                return Boolean.valueOf(pValue);
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Invalid boolean value: " + pValue);
+            }
+        } else if (int.class.equals(pClass)  ||  Integer.class.equals(pClass)) {
+            try {
+                return new Integer(pValue);
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Invalid integer value: " + pValue);
+            }
+        } else if (long.class.equals(pClass)  ||  Long.class.equals(pClass)) {
+            try {
+                return new Long(pValue);
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Invalid long value: " + pValue);
+            }
+        } else if (byte.class.equals(pClass)  ||  Byte.class.equals(pClass)) {
+            try {
+                return new Byte(pValue);
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Invalid byte value: " + pValue);
+            }
+        } else if (short.class.equals(pClass)  ||  Short.class.equals(pClass)) {
+            try {
+                return new Short(pValue);
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Invalid short value: " + pValue);
+            }
+        } else if (char.class.equals(pClass)  ||  Character.class.equals(pClass)) {
+            if (pValue.length() != 1) {
+                throw new IllegalArgumentException("Invalid char value: " + pValue);
+            }
+            return new Character(pValue.charAt(0));
+        } else if (double.class.equals(pClass)  ||  Double.class.equals(pClass)) {
+            try {
+                return new Double(pValue);
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Invalid double value: " + pValue);
+            }
+        } else if (float.class.equals(pClass)  ||  Float.class.equals(pClass)) {
+            try {
+                return new Float(pValue);
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Invalid float value: " + pValue);
+            }
+        } else if (Class.class.equals(pClass)) {
+            try {
+                return Thread.currentThread().getContextClassLoader().loadClass(pValue);
+            } catch (ClassNotFoundException e) {
+                throw new UndeclaredThrowableException(e);
+            }
+        } else {
+            throw new IllegalStateException("Invalid target class: " + pClass.getCanonicalName());
+        }
+    }
+
+    private static Field searchField(Class<?> pClass, String pProperty) {
+        if (pClass == Object.class) {
+            return null;
+        }
+        for (Field f : pClass.getDeclaredFields()) {
+            final String name = f.getName();
+            if (!Strings.isEmpty(pProperty)
+                    &&  name.length() == pProperty.length()
+                    &&  pProperty.length() > 0
+                    &&  Character.toUpperCase(name.charAt(0)) == Character.toUpperCase(pProperty.charAt(0))
+                    &&  name.substring(1).equals(pProperty.substring(1))) {
+                if (!f.isAccessible()) {
+                    f.setAccessible(true);
+                }
+                return f;
+            }
+        }
+        return searchField(pClass.getSuperclass(), pProperty);
+    }
+
+    /**
+     * Returns a field for setting the given property on instances of
+     * the given class.
+     */
+    public static Field getField(Class<?> pClass, String pProperty)
+            throws NoSuchFieldException {
+        final Field f = searchField(pClass, pProperty);
+        if (f == null) {
+            throw new NoSuchFieldException("No field found for property " + pProperty
+                    + " in class " + pClass.getCanonicalName());
+        }
+        return f;
+    }
+
+    /**
+     * Casts the given object to the requested result type.
+     */
+    @SuppressWarnings("unchecked")
+    public static <O> O cast(Object pObject) {
+        return (O) pObject;
+    }
+
+    /**
+     * Returns all fields of the given class {@code pClass}, including
+     * superclasses, and interfaces, which have an annotation of the given
+     * class {@code pAnnotation}.
+     */
+    public static Collection<Field> findAnnotatedFields(Class<?> pClass, Class<Annotation> pAnnotation) {
+        final Set<Class<?>> classes = new HashSet<Class<?>>();
+        final List<Field> fields = new ArrayList<Field>();
+        findAnnotatedFields(classes, fields, pClass, pAnnotation);
+        return fields;
+    }
+
+    private static void findAnnotatedFields(Set<Class<?>> pClasses, List<Field> pFields, Class<?> pClass,
+            Class<Annotation> pAnnotation) {
+        if (!pClasses.contains(pClass)) {
+            for (Field field : pClass.getDeclaredFields()) {
+                if (field.getAnnotation(pAnnotation) != null) {
+                    pFields.add(field);
+                }
+            }
+            final Class<?> superClass = pClass.getSuperclass();
+            if (superClass != null  &&  !superClass.equals(Object.class)) {
+                findAnnotatedFields(pClasses, pFields, superClass, pAnnotation);
+            }
+            for (Class<?> interfaceClass : pClass.getInterfaces()) {
+                findAnnotatedFields(pClasses, pFields, interfaceClass, pAnnotation);
+            }
+        }
+    }
+
+    /**
+     * Returns all setters of the given class {@code pClass}, including
+     * superclasses, and interfaces, which have an annotation of the given
+     * class {@code pAnnotation}.
+     */
+    public static Collection<Method> findAnnotatedSetters(Class<?> pClass, Class<Annotation> pAnnotation) {
+        final Set<Class<?>> classes = new HashSet<Class<?>>();
+        final List<Method> fields = new ArrayList<Method>();
+        findAnnotatedSetters(classes, fields, pClass, pAnnotation);
+        return fields;
+    }
+
+    private static void findAnnotatedSetters(Set<Class<?>> pClasses, List<Method> pMethods, Class<?> pClass,
+            Class<Annotation> pAnnotation) {
+        if (!pClasses.contains(pClass)) {
+            for (Method method : pClass.getDeclaredMethods()) {
+                if (isSetter(method)  &&  method.getAnnotation(pAnnotation) != null) {
+                    pMethods.add(method);
+                }
+            }
+            final Class<?> superClass = pClass.getSuperclass();
+            if (superClass != null  &&  !superClass.equals(Object.class)) {
+                findAnnotatedSetters(pClasses, pMethods, superClass, pAnnotation);
+            }
+            for (Class<?> interfaceClass : pClass.getInterfaces()) {
+                findAnnotatedSetters(pClasses, pMethods, interfaceClass, pAnnotation);
+            }
+        }
+    }
+
+    private static boolean isSetter(Method pMethod) {
+        final String methodName = pMethod.getName();
+        if (!void.class.equals(pMethod.getReturnType())) {
+            return false;
+        }
+        if (methodName.length() < 4  ||  !methodName.startsWith("set")
+                ||  Character.isUpperCase(methodName.charAt(4))) {
+            return false;
+        }
+        final Class<?>[] parameters = pMethod.getParameterTypes();
+        if (parameters.length != 1) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns the URL of the given class.
+     */
+    public static URL getURL(Class<?> pClass) {
+        return pClass.getClassLoader().getResource(pClass.getName().replace('.', '/') + ".class");
+    }
+
+    /**
+     * Returns the value of the property pKey from the object pObject.
+     */
+    public static Object get(Object o, String key) {
+		final Field f;
+		try {
+			f = getField(o.getClass(), key);
+		} catch (NoSuchFieldException e) {
+			Method m;
+			try {
+				m = getGetter(o.getClass(), key);
+			} catch (NoSuchMethodException ex) {
+				throw new UndeclaredThrowableException(ex);
+			}
+			m.setAccessible(true);
+			try {
+				return m.invoke(o);
+			} catch (IllegalArgumentException e1) {
+				throw new UndeclaredThrowableException(e1, "Illegal argument for method " + m
+						+ ": " + o); 
+			} catch (IllegalAccessException e1) {
+				throw new UndeclaredThrowableException(e1, "Illegal access while invoking method " + m
+						+ " with value: " + o);
+			} catch (InvocationTargetException e1) {
+				throw new UndeclaredThrowableException(e1, "Exception while invoking method " + m
+						+ " with value: " + o);
+			}
+		}
+		f.setAccessible(true);
+		try {
+			return f.get(o);
+		} catch (IllegalArgumentException e) {
+			throw new UndeclaredThrowableException(e, "Illegal object for field " + f
+					+ ": " + o); 
+		} catch (IllegalAccessException e) {
+			throw new UndeclaredThrowableException(e, "Illegal access while getting field " + f
+					+ " from object: " + o);
+		}
+    	
+    }
+    /** Sets the property pKey on the object pObject to the given value.
+     */
+	public static void set(Object o, String key, String value) {
+		final Field f;
+		try {
+			f = getField(o.getClass(), key);
+		} catch (NoSuchFieldException e) {
+			Method m;
+			try {
+				m = getSetter(o.getClass(), key);
+			} catch (NoSuchMethodException ex) {
+				throw new UndeclaredThrowableException(ex);
+			}
+			m.setAccessible(true);
+			final Class<?> type = m.getParameterTypes()[0];
+			final Object v;
+			try {
+				v = asValue(type, value);
+			} catch (NamingException ne) {
+				throw new UndeclaredThrowableException(ne);
+			}
+			try {
+				m.invoke(o, v);
+			} catch (IllegalArgumentException e1) {
+				throw new UndeclaredThrowableException(e1, "Illegal argument for method " + m
+						+ ": " + v); 
+			} catch (IllegalAccessException e1) {
+				throw new UndeclaredThrowableException(e1, "Illegal access while invoking method " + m
+						+ " with value: " + v);
+			} catch (InvocationTargetException e1) {
+				throw new UndeclaredThrowableException(e1, "Exception while invoking method " + m
+						+ " with value: " + v);
+			}
+			return;
+		}
+		f.setAccessible(true);
+		final Object v;
+		try {
+			v = asValue(f.getType(), value);
+		} catch (NamingException ne) {
+			throw new UndeclaredThrowableException(ne);
+		}
+		try {
+			f.set(o, v);
+		} catch (IllegalArgumentException e) {
+			throw new UndeclaredThrowableException(e, "Illegal argument for field " + f
+					+ ": " + v); 
+		} catch (IllegalAccessException e) {
+			throw new UndeclaredThrowableException(e, "Illegal access while setting field " + f
+					+ " with value: " + v);
+		}
+	}
+
+	public static Object asValue(Class<?> pClass, final String pValue) throws NamingException {
+		if (String.class.equals(pClass)) {
+			return pValue;
+		} else if (Boolean.TYPE.equals(pClass)  || Boolean.class.equals(pClass)) {
+			return Boolean.valueOf(pValue);
+		} else if (Byte.TYPE.equals(pClass)  || Byte.class.equals(pClass)) {
+			return Byte.parseByte(pValue);
+		} else if (Short.TYPE.equals(pClass)  ||  Short.class.equals(pClass)) {
+			return Short.parseShort(pValue);
+		} else if (Integer.TYPE.equals(pClass)  ||  Integer.class.equals(pClass)) {
+			return Integer.parseInt(pValue);
+		} else if (Long.TYPE.equals(pClass)  ||  Long.class.equals(pClass)) {
+			return Long.parseLong(pValue);
+		} else if (Float.TYPE.equals(pClass)  ||  Float.class.equals(pClass)) {
+			return Float.parseFloat(pValue);
+		} else if (Double.TYPE.equals(pClass)  ||  Double.class.equals(pClass)) {
+			return Double.parseDouble(pValue);
+		} else if (File.class.equals(pClass)) {
+		    return new File(pValue);
+		} else if (pValue.indexOf('.') > 0) {
+			try {
+				return Class.forName(pValue).newInstance();
+			} catch (ClassNotFoundException e) {
+				throw new UndeclaredThrowableException(e, "Value class not found: " + pValue);
+			} catch (InstantiationException e) {
+				throw new UndeclaredThrowableException(e, "Failed to instantiate value class: " + pValue);
+			} catch (IllegalAccessException e) {
+				throw new UndeclaredThrowableException(e, "Illegal access while instantiating value class: " + pValue);
+			}
+		} else {
+			throw new IllegalStateException("Invalid object type: "
+					+ pClass.getName());
+		}
+	}
+}

Added: commons/sandbox/jndi/trunk/commons-jndi/src/main/java/org/apache/commons/jndi/util/Strings.java
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/main/java/org/apache/commons/jndi/util/Strings.java?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/main/java/org/apache/commons/jndi/util/Strings.java (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/main/java/org/apache/commons/jndi/util/Strings.java Wed Sep 26 10:04:12 2012
@@ -0,0 +1,37 @@
+/*
+ * 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.commons.jndi.util;
+
+
+/**
+ * Utility class for working with strings.
+ */
+public class Strings {
+	/**
+	 * Private constructor, to prevent accidental instantiation.
+	 */
+	private Strings() {		
+	}
+
+	public static boolean isEmpty(String pValue) {
+		return pValue == null || pValue.length() == 0;
+	}
+
+	public static String notEmpty(String pValue, String pDefault) {
+		return isEmpty(pValue) ? pDefault : pValue;
+	}
+}

Added: commons/sandbox/jndi/trunk/commons-jndi/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/site/apt/index.apt?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/site/apt/index.apt (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/site/apt/index.apt Wed Sep 26 10:04:12 2012
@@ -0,0 +1,27 @@
+~~
+~~ 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.
+~~
+		============
+		Commons JNDI
+		============
+
+Commons JNDI is a minimal implementation of a JNDI provider and its client,
+based on property, or XML files. The aim is simple configuration and
+suitability for easy use in test cases, not completeness, or anything more
+serious.
+
+See {{{usage.html}this document}} for a description of how to get started
+with Commons JNDI.

Added: commons/sandbox/jndi/trunk/commons-jndi/src/site/apt/usage.apt
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/site/apt/usage.apt?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/site/apt/usage.apt (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/site/apt/usage.apt Wed Sep 26 10:04:12 2012
@@ -0,0 +1,90 @@
+~~
+~~ 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.
+~~
+		=====
+		Usage
+		=====
+
+Usage
+
+    * {{{Creating an InitialContext}}}
+    * {{{Configuring the context contents}}}
+
+* Creating an InitialContext
+
+As is always the case with JNDI, you start by creating an InitialContext.
+This is done by invoking <<<NamingManager.getInitialContext(Properties)>>>
+with a suitable set of properties. In particular, two properties are
+required:
+
++---------------------------+---------------------------+
+|Property name              |Description                |
++---------------------------+---------------------------+
+|java.naming.factory.initial|Contains the class name of the|
+|                           |InitialContextFactory. In the case
+|                           |of Commons JNDI, this is
+|                           |{{{apidocs/org/apache/commons/jndi/CommonsJNDIContextFactory}
+|                           |org.apache.commons.jndi.CommonsJndiContextFactory}}.
++---------------------------+----------------------------+
+|java.naming.provider.url   |An URL in the form          |
+|                           |<<<mem:\<url\>>>>, where url|
+|                           |specifies the URL of a file,|
+|                           |from which to load the      |
+|                           |context contents.           |
++---------------------------+----------------------------+
+
+
++--------------------------------------------------------------------
+    java.util.Properties props = new java.util.Properties();
+    props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.commons.jndi.CommonsJndiContextFactory");
+    java.net.URL url = new File("/etc/myproject/jndi.properties").toURI().toURL();
+    props.setProperty(Context.PROVIDER_URL, "mem:" + url);
+    final InitialContext ctx;
+    try {
+        ctx = javax.naming.spi.NamingManager.getInitialContext(props);
+    } catch (NamingException e) {
+        // Log the error and throw a RuntimeException.
+        throw new java.lang.reflect.UndeclaredThrowableException(e, e.getMessage());
+    }
++--------------------------------------------------------------------
+
+
+* Configuring the context contents
+
+  The initial context contents are read from a resource file. This resource file
+  is configured through the property "java.naming.provider.url", given by the
+  constant <<<Context.PROVIDER_URL>>>. The URL takes the form mem:\<url\>, where
+  <<<\<url\>>>> is any valid java.net.URL, or "resource:\<res\>", if you want to
+  load the resource from the classpath.
+
+  A so-called {{{./apidocs/org/apache/commons/jndi/reader/StreamContextReader.java}context reader}}
+  is instantiated to read the resource file, depending on the URL ending. If the URL ends with
+  ".properties.xml", then it is assumed that the resource file is an XML file matching the
+  {{{http://java.sun.com/dtd/properties.dtd}DTD for Java properties. In that case the
+  context reader is an instance of {{{apidocs//commons-jndi/src/main/java/org/apache/commons/jndi/reader/XmlPropertyReader}XmlPropertyReader}}.
+  Otherwise, if the resource URL ends with <<<.xml>>>, then an
+  {{{apidocs//commons-jndi/src/main/java/org/apache/commons/jndi/reader/XmlReader}XmlReader}} is used
+  and the resource file must meet the {{{./resources/CommonsJNDI.xsd}Commons JNDI XSD}}.
+  In all other cases, the standard format of Java properties is assumed, and a
+  {{{apidocs//commons-jndi/src/main/java/org/apache/commons/jndi/reader/PropertyReader}PropertyReader}}
+  is used to read the resource file.
+
+  * {{{./readers/PropertyReader.html}}Standard Java property files}}
+  * {{{./readers/XmlPropertyReader.html}}Property files in XML format}}
+  * {{{./readers/XmlReader.html}}Files in Commons JNDI XML format}}
+
+  
+  

Added: commons/sandbox/jndi/trunk/commons-jndi/src/site/site.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/site/site.xml?rev=1390365&view=auto
==============================================================================
Binary file - no diff available.

Propchange: commons/sandbox/jndi/trunk/commons-jndi/src/site/site.xml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: commons/sandbox/jndi/trunk/commons-jndi/src/test/filtered-resources/db.properties.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/test/filtered-resources/db.properties.xml?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/test/filtered-resources/db.properties.xml (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/test/filtered-resources/db.properties.xml Wed Sep 26 10:04:12 2012
@@ -0,0 +1,24 @@
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<!--
+ 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.
+-->
+<properties>
+  <entry key="jdbc.driver">org.apache.derby.jdbc.EmbeddedDriver</entry>
+  <entry key="jdbc.dir">${project.build.directory}</entry>
+  <entry key="jdbc.url">jdbc:derby:${project.build.directory}/derbydb;create=true</entry>
+  <entry key="jdbc.user">sa</entry>
+  <entry key="jdbc.password">sa</entry>	
+</properties>

Added: commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/reader/PropertyReaderTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/reader/PropertyReaderTest.java?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/reader/PropertyReaderTest.java (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/reader/PropertyReaderTest.java Wed Sep 26 10:04:12 2012
@@ -0,0 +1,119 @@
+/*
+ * 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.commons.jndi.reader;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import org.apache.commons.jndi.impl.MemoryContext;
+import org.apache.commons.jndi.types.CommonsJNDIDataSource;
+import org.apache.commons.jndi.util.Reflection;
+import org.apache.derby.jdbc.EmbeddedDriver;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PropertyReaderTest {
+	private final Properties newProperties(final String pPrefix) throws Exception {
+		final URL resource = findProperties();
+		final Properties props = new Properties();
+		final InputStream is = resource.openStream();
+		props.load(is);
+		is.close();
+		return props;
+	}
+
+	private URL findProperties() {
+		final URL resource = PropertyReaderTest.class.getClassLoader().getResource("org/apache/commons/jndi/reader/SimpleContext.properties");
+		Assert.assertNotNull(resource);
+		return resource;
+	}
+
+	@Test
+	public void testLoadContextInputStream() throws Exception {
+		final URL resource = findProperties();
+		final InputStream is = resource.openStream();
+		final PropertyReader reader = new PropertyReader();
+		final Context ctx = new MemoryContext();
+		reader.load(ctx, is);
+		is.close();
+		validate(ctx);
+	}
+
+	@Test
+	public void testLoadContextInputStreamPrefix() throws Exception {
+		final URL resource = findProperties();
+		final Properties props = new Properties();
+		final InputStream is = resource.openStream();
+		props.load(is);
+		is.close();
+		final Properties props2 = new Properties();
+		Set<Map.Entry<?,?>> set = Reflection.cast(props.entrySet());
+		for (Map.Entry<?,?> entry : set) {
+			props2.put("xyz." + entry.getKey(), entry.getValue());
+		}
+		final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		props2.store(baos, null);
+		System.out.write(baos.toByteArray());
+		final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+		final PropertyReader reader = new PropertyReader();
+		reader.setPrefix("xyz");
+		final Context ctx = new MemoryContext();
+		reader.load(ctx, bais);
+		bais.close();
+		validate(ctx);
+	}
+
+	@Test
+	public void testLoadContext() throws Exception {
+		final Properties props = new Properties();
+		props.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.commons.jndi.CommonsJNDIContextFactory");
+		props.put(Context.PROVIDER_URL, "mem:resource:///org/apache/commons/jndi/reader/SimpleContext.properties");
+		final Context ix = new InitialContext(props);
+		validate(ix);
+	}
+	
+	void validate(Context pCtx) throws Exception {
+		final CommonsJNDIDataSource d = (CommonsJNDIDataSource) pCtx.lookup("d");
+		Assert.assertNotNull("DataSource d is null", d);
+		Assert.assertEquals(EmbeddedDriver.class.getName(), d.getDriver());
+		Assert.assertEquals("jdbc:derby:/tmp", d.getUrl());
+		Assert.assertEquals("sa", d.getUser());
+		Assert.assertEquals("sa", d.getPassword());
+		final Context subContext = (Context) pCtx.lookup("b");
+		Assert.assertNotNull("Subcontext b is null", subContext);
+		final Object o = subContext.lookup("e");
+		Assert.assertNotNull("Object e in subContext b is null", o);
+		Assert.assertEquals(Object.class, o.getClass());
+		final String f = (String) subContext.lookup("f");
+		Assert.assertEquals("FooBar", f);
+		final CommonsJNDIDataSource c = (CommonsJNDIDataSource) pCtx.lookup("c");
+		Assert.assertNotNull("DataSource d is null", c);
+		Assert.assertEquals(EmbeddedDriver.class.getName(), c.getDriver());
+		Assert.assertEquals("jdbc:derby:/tmp", c.getUrl());
+		Assert.assertEquals("admin", c.getUser());
+		Assert.assertEquals("foo", c.getPassword());
+		
+	}
+}

Added: commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/types/CommonsJNDIDataSourceTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/types/CommonsJNDIDataSourceTest.java?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/types/CommonsJNDIDataSourceTest.java (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/types/CommonsJNDIDataSourceTest.java Wed Sep 26 10:04:12 2012
@@ -0,0 +1,87 @@
+/*
+ * 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.commons.jndi.types;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.Properties;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class CommonsJNDIDataSourceTest {
+	private static String driver, url, user, password;
+
+	@BeforeClass
+	public static void loadProperties() throws Exception {
+		URL u = Thread.currentThread().getContextClassLoader().getResource("db.properties.xml");
+		Assert.assertNotNull(u);
+		final Properties props = new Properties();
+		final InputStream is = u.openStream();
+		props.loadFromXML(is);
+		is.close();
+		driver = requireProperty("jdbc.driver", props);
+		String dir = getProperty("jdbc.dir", props);
+		url = requireProperty("jdbc.url", props);
+		user = requireProperty("jdbc.user", props);
+		password = requireProperty("jdbc.password", props);
+		if (dir != null) {
+			File d = new File(dir);
+			if (!d.isDirectory()  && !d.mkdirs()) {
+				throw new IOException("Unable to create directory: " + d);
+			}
+		}
+		
+	}
+
+	@Test
+	public void testConnecrtion() throws Exception {
+		Class.forName(driver);
+		Connection conn = DriverManager.getConnection(url, user, password);
+		conn.close();
+	}
+
+	@Test
+	public void testDSConnection() throws Exception {
+		final CommonsJNDIDataSource ds = new CommonsJNDIDataSource();
+		ds.setDriver(driver);
+		ds.setUrl(url);
+		ds.setUser(user);
+		ds.setPassword(password);
+		Connection conn = ds.getConnection();
+		Assert.assertNotNull(conn);
+		conn.close();
+	}
+
+	private static String getProperty(String pProperty, final Properties props) {
+		final String v = props.getProperty(pProperty);
+		return v;
+	}
+
+	private static String requireProperty(String pProperty, final Properties props) {
+		final String v = props.getProperty(pProperty);
+		if (v == null) {
+			throw new IllegalStateException("Undefined property: " + pProperty);
+		}
+		return v;
+	}
+}
\ No newline at end of file

Added: commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/Interface.java
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/Interface.java?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/Interface.java (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/Interface.java Wed Sep 26 10:04:12 2012
@@ -0,0 +1,22 @@
+/*
+ * 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.commons.jndi.util;
+
+public interface Interface {
+	void setD(String pValue);
+	String getD();
+}

Added: commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/ReflectionTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/ReflectionTest.java?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/ReflectionTest.java (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/ReflectionTest.java Wed Sep 26 10:04:12 2012
@@ -0,0 +1,73 @@
+/*
+ * 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.commons.jndi.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ReflectionTest {
+	@Test
+	public void testGetGetter() throws Exception {
+		Assert.assertNotNull(Reflection.getGetter(SubClass.class, "a")); 
+		Assert.assertNotNull(Reflection.getGetter(SubClass.class, "b")); 
+		Assert.assertNotNull(Reflection.getGetter(SubClass.class, "c")); 
+		Assert.assertNotNull(Reflection.getGetter(SubClass.class, "d")); 
+	}
+
+	@Test
+	public void testGetSetter() throws Exception {
+		Assert.assertNotNull(Reflection.getSetter(SubClass.class, "a"));
+		Assert.assertNotNull(Reflection.getSetter(SubClass.class, "b"));
+		Assert.assertNotNull(Reflection.getSetter(SubClass.class, "c"));
+		Assert.assertNotNull(Reflection.getSetter(SubClass.class, "d"));
+	}
+
+	@Test
+	public void testGetValue() {
+	}
+
+	@Test
+	public void testGetField() throws Exception {
+		Assert.assertNotNull(Reflection.getField(SubClass.class, "a"));
+		Assert.assertNotNull(Reflection.getField(SubClass.class, "b"));
+		Assert.assertNotNull(Reflection.getField(SubClass.class, "c"));
+	}
+
+	@Test
+	public void testGetURL() {
+		Assert.assertNotNull(Reflection.getURL(Interface.class));
+	}
+
+	@Test
+	public void testSet() {
+		final SimpleBean bean = new SimpleBean();
+		Assert.assertNull(bean.getA());
+		Assert.assertNull(bean.getB());
+		Assert.assertNull(Reflection.get(bean, "a"));
+		Assert.assertNull(Reflection.get(bean, "b"));
+		final String aVal = "Value of a";
+		final String bVal = "Value of b";
+		Reflection.set(bean, "a", aVal);
+		Reflection.set(bean, "b", bVal);
+		Assert.assertEquals(aVal, bean.getA());
+		Assert.assertEquals(bVal, bean.getB());
+		Assert.assertEquals(aVal, Reflection.get(bean, "a"));
+		Assert.assertEquals(bVal, Reflection.get(bean, "b"));
+		
+	}
+
+}

Added: commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SimpleBean.java
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SimpleBean.java?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SimpleBean.java (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SimpleBean.java Wed Sep 26 10:04:12 2012
@@ -0,0 +1,33 @@
+/*
+ * 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.commons.jndi.util;
+
+public class SimpleBean {
+	private String a, b;
+
+	public String getB() {
+		return b;
+	}
+
+	public String getA() {
+		return a;
+	}
+
+	public void setA(String a) {
+		this.a = a;
+	}
+}

Added: commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SubClass.java
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SubClass.java?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SubClass.java (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SubClass.java Wed Sep 26 10:04:12 2012
@@ -0,0 +1,42 @@
+/*
+ * 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.commons.jndi.util;
+
+public class SubClass extends SuperClass implements Interface {
+	private String b, d;
+	private boolean c;
+	
+
+	public String getD() {
+		return d;
+	}
+	public void setD(String pD) {
+		d = pD;
+	}
+	public String getB() {
+		return b;
+	}
+	public void setB(String pB) {
+		b = pB;
+	}
+	public boolean isC() {
+		return c;
+	}
+	public void setC(boolean pC) {
+		c = pC;
+	}
+}

Added: commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SuperClass.java
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SuperClass.java?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SuperClass.java (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/test/java/org/apache/commons/jndi/util/SuperClass.java Wed Sep 26 10:04:12 2012
@@ -0,0 +1,30 @@
+/*
+ * 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.commons.jndi.util;
+
+public class SuperClass {
+	private String a;
+
+	public String getA() {
+		return a;
+	}
+
+	public void setA(String pA) {
+		a = pA;
+	}
+	
+}

Added: commons/sandbox/jndi/trunk/commons-jndi/src/test/resources/org/apache/commons/jndi/reader/SimpleContext.properties
URL: http://svn.apache.org/viewvc/commons/sandbox/jndi/trunk/commons-jndi/src/test/resources/org/apache/commons/jndi/reader/SimpleContext.properties?rev=1390365&view=auto
==============================================================================
--- commons/sandbox/jndi/trunk/commons-jndi/src/test/resources/org/apache/commons/jndi/reader/SimpleContext.properties (added)
+++ commons/sandbox/jndi/trunk/commons-jndi/src/test/resources/org/apache/commons/jndi/reader/SimpleContext.properties Wed Sep 26 10:04:12 2012
@@ -0,0 +1,34 @@
+# 
+#  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.
+# 
+objects=a b,c
+a.\:name=d
+a.\:type=datasource
+a.driver=org.apache.derby.jdbc.EmbeddedDriver
+a.url=jdbc\:derby\:/tmp
+a.user=sa
+a.password=sa
+b.\:type=context
+b.:name=env
+b.objects=e f
+b.e.\:type=java.lang.Object
+b.f.\:type=java.lang.String
+b.f.value=FooBar
+c.\:type=javax.sql.DataSource
+c.driver=org.apache.derby.jdbc.EmbeddedDriver
+c.url=jdbc\:derby\:/tmp
+c.user=admin
+c.password=foo