geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d...@apache.org
Subject svn commit: r290873 [2/2] - in /geronimo: branches/1.0-M5/ branches/1.0-M5/modules/assembly/src/plan/ branches/1.0-M5/modules/common/src/java/org/apache/geronimo/common/propertyeditor/ branches/1.0-M5/modules/common/src/test/org/apache/geronimo/common/...
Date Thu, 22 Sep 2005 01:08:05 GMT
Modified: geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/PropertyEditors.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/PropertyEditors.java?rev=290873&r1=290872&r2=290873&view=diff
==============================================================================
--- geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/PropertyEditors.java
(original)
+++ geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/PropertyEditors.java
Wed Sep 21 18:07:45 2005
@@ -20,119 +20,142 @@
 import java.beans.PropertyEditor;
 import java.beans.PropertyEditorManager;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import org.apache.geronimo.kernel.ClassLoading;
 
 /**
- * A collection of PropertyEditor utilities.
+ * The property editor manager.  This orchestrates Geronimo usage of
+ * property editors, allowing additional search paths to be added and
+ * specific editors to be registered.
  *
- * <p>Allows editors to be nested sub-classes named PropertyEditor.
- *
- * @version $Rev$ $Date$
+ * @version $Rev$
  */
-public class PropertyEditors
-{
+public class PropertyEditors {
     /**
-     * Augment the PropertyEditorManager search path to incorporate the
-     * Geronimo specific editors.
+     * We need to register the standard register seach path and explicitly
+     * register a boolean editor to make sure ours overrides.
      */
-    static
-    {
-        // Append our package to the serach path
+    static {
+        // Append the geronimo propertyeditors package to the global search path.
         appendEditorSearchPath("org.apache.geronimo.common.propertyeditor");
+        // and explicitly register the Boolean editor.
         PropertyEditorManager.registerEditor(Boolean.class, BooleanEditor.class);
     }
 
     /**
-     * Locate a value editor for a given target type.
+     * Locate an editor for qiven class of object.
      *
-     * @param type   The class of the object to be edited.
-     * @return       An editor for the given type or null if none was found.
+     * @param type The target object class of the property.
+     * @return The resolved editor, if any.  Returns null if a suitable editor
+     *         could not be located.
      */
-    public static PropertyEditor findEditor(final Class type)
-    {
+    public static PropertyEditor findEditor(Class type) {
+        // explicit argument checking is required.
         if (type == null) {
             throw new IllegalArgumentException("type is null");
         }
 
+
+        // try to locate this directly from the editor manager first.
         PropertyEditor editor = PropertyEditorManager.findEditor(type);
 
-        // Try to use adapter for array types
-        if (editor == null && type.isArray()) {
-            Class ctype = type.getComponentType();
-            editor = findEditor(ctype);
+        // we're outta here if we got one.
+        if (editor != null) {
+            return editor;
+        }
+
+        // it's possible this was a request for an array class.  We might not
+        // recognize the array type directly, but the component type might be
+        // resolvable
+        if (type.isArray()) {
+            // do a recursive lookup on the base type
+            editor = findEditor(type.getComponentType());
+            // if we found a suitable editor for the base component type,
+            // wrapper this in an array adaptor for real use
             if (editor != null) {
-                editor = new ArrayPropertyEditorAdapter(ctype, editor);
+                return new ArrayPropertyEditorAdapter(type.getComponentType(), editor);
             }
         }
-
-        return editor;
+        // nothing found
+        return null;
     }
 
     /**
-     * Locate a value editor for a given target type.
+     * Locate an editor for qiven class of object, resolved within the context of
+     * a specific ClassLoader instance.
      *
-     * @param typeName    The class name of the object to be edited.
-     * @return            An editor for the given type or null if none was found.
+     * @param typeName The type name of target property class.
+     * @param loader The source ClassLoader instance.
+     * @return The resolved editor, if any.  Returns null if a suitable editor
+     *         could not be located.
+     * @throws ClassNotFoundException Thrown if unable to resolve an appropriate editor class.
      */
-    public static PropertyEditor findEditor(final String typeName, ClassLoader classLoader)
-        throws ClassNotFoundException
-    {
+    public static PropertyEditor findEditor(String typeName, ClassLoader loader) throws ClassNotFoundException
{
+        // explicit argument checking is required.
         if (typeName == null) {
             throw new IllegalArgumentException("typeName is null");
         }
 
         Class type = null;
+        // load using the ClassLoading utility, which also manages arrays and primitive classes.
         try {
-            type = ClassLoading.loadClass(typeName, classLoader);
-        }
-        catch (ClassNotFoundException e) {
-            // look for a nested class
-            type = ClassLoading.loadClass(typeName + "$PropertyEditor", classLoader);
+            type = ClassLoading.loadClass(typeName, loader);
+        } catch (ClassNotFoundException e) {
+            // We also support anonymous inner class nesting of property editors.  In that
situation,
+            // the package/class names are the same, but add on the inner class specifier.
+            // If this one fails, we jump directly out with the ClassNotFoundException.
+            type = ClassLoading.loadClass(typeName + "$PropertyEditor", loader);
         }
 
-        // PropertyEditorManager uses the classloader for object, then system, them context
-        // We need to force the context loader to that of the user as the Editor may be
-        // located in a child loader from the type being loader 
+        // The PropertyEditorManager class uses the context class loader for all of its resolution
+        // steps.  We need force PropertyManagerEditor to use our loader, so we override
the
+        // current context loader.
         ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
         try {
-            Thread.currentThread().setContextClassLoader(classLoader);
+            Thread.currentThread().setContextClassLoader(loader);
+            // now call the base findEditor() method that works directly from the property
type.
             return findEditor(type);
         } finally {
+            // make sure we restore the context....this will happen even if findEditor()
+            // results in an exception.
             Thread.currentThread().setContextClassLoader(oldLoader);
         }
     }
 
     /**
-     * Get a value editor for a given target type.
+     * Get a property editor for a given property type.  This is like
+     * findEditor, but throws an exception if the property is not found.
      *
-     * @param type    The class of the object to be edited.
-     * @return        An editor for the given type.
-     *
-     * @throws PropertyEditorException   No editor was found.
+     * @param type The target object class of the property.
+     * @return The resolved editor, if any.  Throws an exception if this cannot
+     *         be resolved.
+     * @throws PropertyEditorException Unable to find a suitable editor for this class.
      */
-    public static PropertyEditor getEditor(final Class type)
-    {
+    public static PropertyEditor getEditor(Class type) {
+        // just call the non-exceptional lookup
         PropertyEditor editor = findEditor(type);
+        // this one throws an exception if not found.
         if (editor == null) {
             throw new PropertyEditorException("No property editor for type: " + type);
         }
-
         return editor;
     }
 
     /**
-     * Register an editor class to be used to editor values of a given target class.
+     * Explicity register an editor class for a given target class.
      *
-     * @param type         The class of the objetcs to be edited.
-     * @param editorType   The class of the editor.
+     * @param type The property class.
+     * @param editorType The editor class matched up with this type.
      */
-    public static void registerEditor(final Class type, final Class editorType)
-    {
+    public static void registerEditor(Class type, Class editorType) {
+        // explicit argument checking is required.
         if (type == null) {
             throw new IllegalArgumentException("type is null");
         }
+
+        // explicit argument checking is required.
         if (editorType == null) {
             throw new IllegalArgumentException("editorType is null");
         }
@@ -141,110 +164,132 @@
     }
 
     /**
-     * Register an editor class to be used to editor values of a given target class.
+     * Explicity register a property/editor class pair by class name.
      *
-     * @param typeName         The classname of the objetcs to be edited.
-     * @param editorTypeName   The class of the editor.
+     * @param typeName The classname of the property.
+     * @param editorName The classname of the property editor.
+     * @throws ClassNotFoundException Thrown if unable to resolve either the type or the
editor from their names.
      */
-    public static void registerEditor(final String typeName,
-                                      final String editorTypeName)
-        throws ClassNotFoundException
-    {
+    public static void registerEditor(String typeName, String editorName) throws ClassNotFoundException
{
+        // explicit argument checking is required.
         if (typeName == null) {
             throw new IllegalArgumentException("typeName is null");
         }
-        if (editorTypeName == null) {
+
+        // explicit argument checking is required.
+        if (editorName == null) {
             throw new IllegalArgumentException("editorTypeName is null");
         }
+        // we use the current context loader for this
+        ClassLoader loader = Thread.currentThread().getContextClassLoader();
 
-        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-        Class type = ClassLoading.loadClass(typeName, classLoader);
-        Class editorType = ClassLoading.loadClass(editorTypeName, classLoader);
+        // load both of these loaders using our ClassLoading support.
+        Class type = ClassLoading.loadClass(typeName, loader);
+        Class editor = ClassLoading.loadClass(editorName, loader);
 
-        registerEditor(type, editorType);
+        // we have resolved classes, so register the class information.
+        registerEditor(type, editor);
     }
 
     /**
-     * Gets the package names that will be searched for property editors.
+     * Get a list containing all of the packages in the editor search path.
      *
-     * @return   The package names that will be searched for property editors.
+     * @return a List object containing all of the registered search paths.
      */
-    public static List getEditorSearchPath()
-    {
-        String[] path = PropertyEditorManager.getEditorSearchPath();
+    public static List getEditorSearchPath() {
+        // grrrr, Arrays.asList() returns a readonly List item, which makes it difficult
+        // to append additional items.  This means we have to do this manually.
+
+        // start by getting the list from the editor manager, which is returned as an
+        // array of Strings.
+        String[] paths = PropertyEditorManager.getEditorSearchPath();
+
+        // get a list matching the initial size...we don't always request this with the intend
to append.
+        List pathList = new ArrayList(paths.length);
 
-        List list = new ArrayList(path.length);
-        for (int i=0; i<path.length; i++) {
-            list.add(path[i]);
+        // now MANUALLY add each of the items in the array.
+        for (int i = 0; i < paths.length; i++) {
+            pathList.add(paths[i]);
         }
 
-        return list;
+        return pathList;
     }
 
     /**
-     * Sets the package names that will be searched for property editors.
+     * Sets the search order used for property editor resolution.
      *
-     * @param path   The serach path.
+     * @param path The serach path.
      */
-    public static void setEditorSearchPath(final List path)
-    {
+    public static void setEditorSearchPath(List path) {
+        // explicit argument checking is required.
         if (path == null) {
             throw new IllegalArgumentException("path is null");
         }
 
-        String[] elements = (String[])path.toArray(new String[path.size()]);
+        // we deal in Lists, PropertyEditorManager does arrays, so we need to
+        // extract the elements into a array of Strings.
+        String[] elements = (String[]) path.toArray(new String[path.size()]);
         PropertyEditorManager.setEditorSearchPath(elements);
     }
 
     /**
-     * Append package names to the property editor search path.
+     * Append additional package names to the property editor search path.
      *
-     * @param names   The package names to append.
+     * @param names The package names to append.
      */
-    public static void appendEditorSearchPath(final List names)
-    {
-        if (names == null) {
+    public static void appendEditorSearchPath(List newNames) {
+        // explicit argument checking is required.
+        if (newNames == null) {
             throw new IllegalArgumentException("names is null");
         }
-        if (names.size() == 0) return;
 
-        List path = getEditorSearchPath();
-        path.addAll(names);
+        // if there's nothing to do, then do nothing :-)
+        if (newNames.isEmpty()) {
+            return;
+        }
+
+        // append to the current names list, and set ammended list back as the current
+        // search order.
+        List currentPath = getEditorSearchPath();
+        currentPath.addAll(newNames);
 
-        setEditorSearchPath(path);
+        setEditorSearchPath(currentPath);
     }
 
     /**
-     * Append package names to the property editor search path.
+     * Append an array of package names to the editor search path.
      *
-     * @param names   The package names to append.
+     * @param names A string array containing the added names.
      */
-    public static void appendEditorSearchPath(final String[] names)
-    {
-        if (names == null) {
+    public static void appendEditorSearchPath(String[] newNames) {
+        // explicit argument checking is required.
+        if (newNames == null) {
             throw new IllegalArgumentException("names is null");
         }
-        if (names.length == 0) return;
 
-        List list = new ArrayList(names.length);
-        for (int i=0; i<names.length; i++) {
-            list.add(names[i]);
+        // only bother continuing if the array contains something.
+        if (newNames.length != 0) {
+            // just convert this to a list and add as normal.
+            appendEditorSearchPath(Arrays.asList(newNames));
         }
-
-        appendEditorSearchPath(list);
     }
 
     /**
-     * Append a package name to the property editor search path.
+     * Append a single package name to the editor search path.
      *
-     * @param name   The package name to append.
+     * @param name The new path name.
      */
-    public static void appendEditorSearchPath(final String name)
-    {
-        if (name == null) {
+    public static void appendEditorSearchPath(String newName) {
+        // explicit argument checking is required.
+        if (newName == null) {
             throw new IllegalArgumentException("name is null");
         }
 
-        appendEditorSearchPath(new String[] { name });
+        // append to the current names list, and set ammended list back as the current
+        // search order.
+        List currentPath = getEditorSearchPath();
+        currentPath.add(newName);
+
+        setEditorSearchPath(currentPath);
     }
 }

Modified: geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/TextPropertyEditorSupport.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/TextPropertyEditorSupport.java?rev=290873&r1=290872&r2=290873&view=diff
==============================================================================
--- geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/TextPropertyEditorSupport.java
(original)
+++ geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/TextPropertyEditorSupport.java
Wed Sep 21 18:07:45 2005
@@ -20,30 +20,36 @@
 import java.beans.PropertyEditorSupport;
 
 /**
- * A property editor support class for textual properties.
+ * A base class for text based properties.  This class basically does nothing
+ * but override the defaute PropertyEditorSupport setAsText() method, which
+ * throws an IllegalArgumentException when called.
  *
- * @version $Rev$ $Date$
+ * @version $Rev$
  */
-public class TextPropertyEditorSupport
-    extends PropertyEditorSupport
-{
-    protected TextPropertyEditorSupport(final Object source)
-    {
+public class TextPropertyEditorSupport extends PropertyEditorSupport {
+    /**
+     * A property editor with a provided source object.
+     *
+     * @param source The source of the editted information.
+     */
+    protected TextPropertyEditorSupport(Object source) {
         super(source);
     }
-    
-    protected TextPropertyEditorSupport()
-    {
+
+    /**
+     * Default no-argument constructor.
+     */
+    protected TextPropertyEditorSupport() {
         super();
     }
-    
+
     /**
-     * Sets the property value by parsing a given String.
+     * By default, set the property value by directly passing the
+     * provided string value through to the setValue() method.
      *
-     * @param text  The string to be parsed.
+     * @param value The new property value, as a string.
      */
-    public void setAsText(final String text)
-    {
-        setValue(text);
+    public void setAsText(String value) {
+        setValue(value);
     }
 }

Modified: geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/URLEditor.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/URLEditor.java?rev=290873&r1=290872&r2=290873&view=diff
==============================================================================
--- geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/URLEditor.java
(original)
+++ geronimo/trunk/modules/common/src/java/org/apache/geronimo/common/propertyeditor/URLEditor.java
Wed Sep 21 18:07:45 2005
@@ -14,7 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package org.apache.geronimo.common.propertyeditor;
 
 import java.io.File;
@@ -22,39 +21,49 @@
 import java.net.URL;
 
 /**
- * A property editor for {@link java.net.URL}.
+ * A property editor for URL typed properties.
  *
- * @version $Rev$ $Date$
+ * @version $Rev$
  */
 public class URLEditor extends TextPropertyEditorSupport {
     /**
-     * Returns a URL for the input object converted to a string.
-     *
-     * @return a URL object
+     * Convert the text value of the property into a URL object instance.
      *
-     * @throws PropertyEditorException   An MalformedURLException occured.
+     * @return a URL object constructed from the property text value.
      */
     public Object getValue() {
         try {
-            String urlspec = getAsText().trim();
-            URL url;
+            // try to create directly from the text property.
+            URL url = new URL(getAsText().trim());
+            // this parsed correctly, but if this is a file object,
+            // we need to make sure this gets converted into the proper
+            // absolute directory form.
             try {
-                url = new URL(urlspec);
                 if (url.getProtocol().equals("file")) {
-                    url = createFromFilespec(url.getFile());
+                    // ok, this is a file URL, so get the file string portion,
+                    // convert that to a file object, then go through the URI()/URL()
+                    // conversion sequence to get a fully valid URL().
+                    return new File(url.getFile()).toURI().toURL();
                 }
             } catch (Exception e) {
-                url = createFromFilespec(urlspec);
+                // any error here is returned as a property editor exception.
+                throw new PropertyEditorException(e);
             }
 
             return url;
+        } catch (MalformedURLException e) {
+            // this is a format error, but it could have been specified as a local
+            // file name. so try to create a file object and make a URL from that.
+        }
 
+        try {
+            // The file class has direct support for returning as a URL, but the Javadoc
+            // for File.toURL() recommends converting the File object to a URI first
+            // so that untranslatable characters get handled correctly.
+            return new File(getAsText()).toURI().toURL();
         } catch (MalformedURLException e) {
+            // any error here is returned as a property editor exception.
             throw new PropertyEditorException(e);
         }
-    }
-
-    private static URL createFromFilespec(final String filespec) throws MalformedURLException
{
-        return new File(filespec).toURI().toURL();
     }
 }

Added: geronimo/trunk/modules/common/src/test/org/apache/geronimo/common/propertyeditor/URLEditorTest.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/common/src/test/org/apache/geronimo/common/propertyeditor/URLEditorTest.java?rev=290873&view=auto
==============================================================================
--- geronimo/trunk/modules/common/src/test/org/apache/geronimo/common/propertyeditor/URLEditorTest.java
(added)
+++ geronimo/trunk/modules/common/src/test/org/apache/geronimo/common/propertyeditor/URLEditorTest.java
Wed Sep 21 18:07:45 2005
@@ -0,0 +1,68 @@
+/**
+ *
+ * Copyright 2003-2004 The Apache Software Foundation
+ *
+ *  Licensed 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.geronimo.common.propertyeditor;
+
+import java.beans.PropertyEditor;
+import java.io.File;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link URLEditor} class.
+ *
+ * @version $Rev$
+ */
+public class URLEditorTest extends TestCase {
+    PropertyEditor editor;
+
+    protected void setUp() {
+        editor = PropertyEditors.findEditor(URL.class);
+    }
+
+    public void testEditorClass() throws Exception {
+        assertEquals(URLEditor.class, editor.getClass());
+    }
+
+    public void testHTTP() throws Exception {
+        checkURL("http://www.apache.org", null);
+    }
+
+    public void testFTP() throws Exception {
+        checkURL("ftp://ftp.apache.org", null);
+    }
+
+    public void testFileURL() throws Exception {
+        URL base = new URL("file://test.resource");
+        base = new File(base.getFile()).toURI().toURL();
+        checkURL("file://test.resource", base);
+    }
+
+    public void testFile() throws Exception {
+        URL testValue = new File("test.resource").toURI().toURL();
+        checkURL("test.resource", testValue);
+    }
+
+    protected void checkURL(String text, URL test) throws Exception {
+        editor.setAsText(text);
+        if (test == null) {
+            test = new URL(text);
+        }
+        assertEquals(test, editor.getValue());
+    }
+}

Propchange: geronimo/trunk/modules/common/src/test/org/apache/geronimo/common/propertyeditor/URLEditorTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/trunk/modules/common/src/test/org/apache/geronimo/common/propertyeditor/URLEditorTest.java
------------------------------------------------------------------------------
    svn:keywords = "Date Rev Id"

Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/ClassLoading.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/ClassLoading.java?rev=290873&r1=290872&r2=290873&view=diff
==============================================================================
--- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/ClassLoading.java (original)
+++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/ClassLoading.java Wed
Sep 21 18:07:45 2005
@@ -19,207 +19,243 @@
 
 import java.lang.reflect.Array;
 import java.util.HashMap;
-import java.util.Map;
 
 /**
- * Utilities for loading classes.
+ * Utility class for loading classes by a variety of name variations.
+ * <p/>
+ * Supported names types are:
+ * <p/>
+ * 1)  Fully qualified class name (e.g., "java.lang.String", "org.apache.geronimo.kernel.ClassLoading"
+ * 2)  Method signature encoding ("Ljava.lang.String;", "J", "I", etc.)
+ * 3)  Primitive type names ("int", "boolean", etc.)
+ * 4)  Method array signature strings ("[I", "[Ljava.lang.String")
+ * 5)  Arrays using Java code format ("int[]", "java.lang.String[][]")
+ * <p/>
+ * The classes are loaded using the provided class loader.  For the basic types, the primitive
+ * reflection types are returned.
  *
- * @version $Rev$ $Date$
+ * @version $Rev$
  */
 public class ClassLoading {
+
+    /**
+     * Table for mapping primitive class names/signatures to the implementing
+     * class object
+     */
+    private static final HashMap PRIMITIVE_CLASS_MAP = new HashMap();
+
+    /**
+     * Table for mapping primitive classes back to their name signature type, which
+     * allows a reverse mapping to be performed from a class object into a resolvable
+     * signature.
+     */
+    private static final HashMap CLASS_TO_SIGNATURE_MAP = new HashMap();
+
+
     /**
-     * Load a class for the given name.
+     * Setup the primitives map.  We make any entry for each primitive class using both the
+     * human readable name and the method signature shorthand type.
+     */
+    static {
+        PRIMITIVE_CLASS_MAP.put("boolean", boolean.class);
+        PRIMITIVE_CLASS_MAP.put("Z", boolean.class);
+        PRIMITIVE_CLASS_MAP.put("byte", byte.class);
+        PRIMITIVE_CLASS_MAP.put("B", byte.class);
+        PRIMITIVE_CLASS_MAP.put("char", char.class);
+        PRIMITIVE_CLASS_MAP.put("C", char.class);
+        PRIMITIVE_CLASS_MAP.put("short", short.class);
+        PRIMITIVE_CLASS_MAP.put("S", short.class);
+        PRIMITIVE_CLASS_MAP.put("int", int.class);
+        PRIMITIVE_CLASS_MAP.put("I", int.class);
+        PRIMITIVE_CLASS_MAP.put("long", long.class);
+        PRIMITIVE_CLASS_MAP.put("J", long.class);
+        PRIMITIVE_CLASS_MAP.put("float", float.class);
+        PRIMITIVE_CLASS_MAP.put("F", float.class);
+        PRIMITIVE_CLASS_MAP.put("double", double.class);
+        PRIMITIVE_CLASS_MAP.put("D", double.class);
+        PRIMITIVE_CLASS_MAP.put("void", void.class);
+        PRIMITIVE_CLASS_MAP.put("V", void.class);
+
+        // Now build a reverse mapping table.  The table above has a many-to-one mapping
for
+        // class names.  To do the reverse, we need to pick just one.  As long as the
+        // returned name supports "round tripping" of the requests, this will work fine.
+
+        CLASS_TO_SIGNATURE_MAP.put(boolean.class, "Z");
+        CLASS_TO_SIGNATURE_MAP.put(byte.class, "B");
+        CLASS_TO_SIGNATURE_MAP.put(char.class, "C");
+        CLASS_TO_SIGNATURE_MAP.put(short.class, "S");
+        CLASS_TO_SIGNATURE_MAP.put(int.class, "I");
+        CLASS_TO_SIGNATURE_MAP.put(long.class, "J");
+        CLASS_TO_SIGNATURE_MAP.put(float.class, "F");
+        CLASS_TO_SIGNATURE_MAP.put(double.class, "D");
+        CLASS_TO_SIGNATURE_MAP.put(void.class, "V");
+    }
+
+
+    /**
+     * Load a class that matches the requested name, using the provided class loader context.
      * <p/>
-     * <p>Handles loading primitive types as well as VM class and array syntax.
+     * The class name may be a standard class name, the name of a primitive type Java
+     * reflection class (e.g., "boolean" or "int"), or a type in method type signature
+     * encoding.  Array classes in either encoding form are also processed.
      *
-     * @param className The name of the Class to be loaded.
-     * @param classLoader The class loader to load the Class object from.
-     * @return The Class object for the given name.
-     * @throws ClassNotFoundException Failed to load Class object.
+     * @param className The name of the required class.
+     * @param classLoader The class loader used to resolve the class object.
+     * @return The Class object resolved from "className".
+     * @throws ClassNotFoundException When unable to resolve the class object.
+     * @throws IllegalArgumentException If either argument is null.
      */
-    public static Class loadClass(final String className, final ClassLoader classLoader)
throws ClassNotFoundException {
+    public static Class loadClass(String className, ClassLoader classLoader) throws ClassNotFoundException
{
+
+        // the tests require IllegalArgumentExceptions for null values on either of these.
         if (className == null) {
             throw new IllegalArgumentException("className is null");
         }
+
         if (classLoader == null) {
             throw new IllegalArgumentException("classLoader is null");
         }
-
-        // First just try to load
+        // The easiest case is a proper class name.  We just have the class loader resolve
this.
+        // If the class loader throws a ClassNotFoundException, then we need to check each
of the
+        // special name encodings we support.
         try {
             return classLoader.loadClass(className);
         } catch (ClassNotFoundException ignore) {
-            // handle special cases below
+            // if not found, continue on to the other name forms.
         }
 
-        Class type = null;
 
-        // Check if it is a primitive type
-        type = getPrimitiveType(className);
-        if (type != null) return type;
-
-        // Check if it is a vm primitive
-        type = getVMPrimitiveType(className);
-        if (type != null) return type;
+        // The second easiest version to resolve is a direct map to a primitive type name
+        // or method signature.  Check our name-to-class map for one of those.
+        Class resolvedClass = (Class) PRIMITIVE_CLASS_MAP.get(className);
+        if (resolvedClass != null) {
+            return resolvedClass;
+        }
 
-        // Handle VM class syntax (Lclassname;)
-        if (className.charAt(0) == 'L' && className.charAt(className.length() - 1)
== ';') {
-            return classLoader.loadClass(className.substring(1, className.length() - 1));
+        // Class names in method signature have the format "Lfully.resolved.name;",
+        // so if it ends in a semicolon and begins with an "L", this must be in
+        // this format.  Have the class loader try to load this.  There are no other
+        // options if this fails, so just allow the class loader to throw the
+        // ClassNotFoundException.
+        if (className.endsWith(";") && className.startsWith("L")) {
+            // pick out the name portion
+            String typeName = className.substring(1, className.length() - 1);
+            // and delegate the loading to the class loader.
+            return classLoader.loadClass(typeName);
         }
 
-        // Handle VM array syntax ([type)
-        if (className.charAt(0) == '[') {
-            int arrayDimension = className.lastIndexOf('[') + 1;
-            String componentClassName = className.substring(arrayDimension, className.length());
-            type = loadClass(componentClassName, classLoader);
+        // All we have left now are the array types.  Method signature array types
+        // have a series of leading "[" characters to specify the number of dimensions.
+        // The other array type we handle uses trailing "[]" for the dimensions, just
+        // like the Java language syntax.
 
-            int dim[] = new int[arrayDimension];
-            java.util.Arrays.fill(dim, 0);
-            return Array.newInstance(type, dim).getClass();
-        }
+        // first check for the signature form ([[[[type).
+        if (className.charAt(0) == '[') {
+            // we have at least one array marker, now count how many leading '['s we have
+            // to get the dimension count.
+            int count = 0;
+            int nameLen = className.length();
 
-        // Handle user friendly type[] syntax
-        if (className.endsWith("[]")) {
-            // get the base component class name and the arrayDimensions
-            int arrayDimension = 0;
-            String componentClassName = className;
-            while (componentClassName.endsWith("[]")) {
-                componentClassName = componentClassName.substring(0, componentClassName.length()
- 2);
-                arrayDimension++;
+            while (count < nameLen && className.charAt(count) == '[') {
+                count++;
             }
 
-            // load the base type
-            type = loadClass(componentClassName, classLoader);
-
-            // return the array type
-            int[] dim = new int[arrayDimension];
-            java.util.Arrays.fill(dim, 0);
-            return Array.newInstance(type, dim).getClass();
+            // pull of the name subtype, which is everything after the last '['
+            String arrayTypeName = className.substring(count, className.length());
+            // resolve the type using a recursive call, which will load any of the primitive
signature
+            // types as well as class names.
+            Class arrayType = loadClass(arrayTypeName, classLoader);
+
+            // Resolving array types require a little more work.  The array classes are
+            // created dynamically when the first instance of a given dimension and type
is
+            // created.  We need to create one using reflection to do this.
+            return getArrayClass(arrayType, count);
         }
 
-        // Else we can not load (give up)
-        throw new ClassNotFoundException(className);
-    }
 
-    public static String getClassName(Class clazz) {
-        StringBuffer rc = new StringBuffer();
-        while (clazz.isArray()) {
-            rc.append('[');
-            clazz = clazz.getComponentType();
-        }
-        if (!clazz.isPrimitive()) {
-            rc.append('L');
-            rc.append(clazz.getName());
-            rc.append(';');
-        } else {
-            rc.append(VM_PRIMITIVES_REVERSE.get(clazz));
-        }
-        return rc.toString();
-    }
+        // ok, last chance.  Now check for an array specification in Java language
+        // syntax.  This will be a type name followed by pairs of "[]" to indicate
+        // the number of dimensions.
+        if (className.endsWith("[]")) {
+            // get the base component class name and the arrayDimensions
+            int count = 0;
+            int position = className.length();
 
-    /**
-     * Primitive type name -> class map.
-     */
-    private static final Map PRIMITIVES = new HashMap();
+            while (position > 1 && className.substring(position - 2, position).equals("[]"))
{
+                // count this dimension
+                count++;
+                // and step back the probe position.
+                position -= 2;
+            }
 
-    /** Setup the primitives map. */
-    static {
-        PRIMITIVES.put("boolean", Boolean.TYPE);
-        PRIMITIVES.put("byte", Byte.TYPE);
-        PRIMITIVES.put("char", Character.TYPE);
-        PRIMITIVES.put("short", Short.TYPE);
-        PRIMITIVES.put("int", Integer.TYPE);
-        PRIMITIVES.put("long", Long.TYPE);
-        PRIMITIVES.put("float", Float.TYPE);
-        PRIMITIVES.put("double", Double.TYPE);
-        PRIMITIVES.put("void", Void.TYPE);
-    }
+            // position now points at the location of the last successful test.  This makes
it
+            // easy to pick off the class name.
 
-    /**
-     * Get the primitive type for the given primitive name.
-     *
-     * @param name Primitive type name (boolean, byte, int, ...)
-     * @return Primitive type or null.
-     */
-    private static Class getPrimitiveType(final String name) {
-        return (Class) PRIMITIVES.get(name);
-    }
+            String typeName = className.substring(0, position);
 
-    /**
-     * VM primitive type name -> primitive type
-     */
-    private static final HashMap VM_PRIMITIVES = new HashMap();
+            // load the base type, again, doing this recursively
+            Class arrayType = loadClass(typeName, classLoader);
+            // and turn this into the class object
+            return getArrayClass(arrayType, count);
+        }
 
-    /** Setup the vm primitives map. */
-    static {
-        VM_PRIMITIVES.put("B", byte.class);
-        VM_PRIMITIVES.put("C", char.class);
-        VM_PRIMITIVES.put("D", double.class);
-        VM_PRIMITIVES.put("F", float.class);
-        VM_PRIMITIVES.put("I", int.class);
-        VM_PRIMITIVES.put("J", long.class);
-        VM_PRIMITIVES.put("S", short.class);
-        VM_PRIMITIVES.put("Z", boolean.class);
-        VM_PRIMITIVES.put("V", void.class);
+        // We're out of options, just toss an exception over the wall.
+        throw new ClassNotFoundException(className);
     }
 
-    /**
-     * VM primitive type primitive type ->  name
-     */
-    private static final HashMap VM_PRIMITIVES_REVERSE = new HashMap();
-
-    /** Setup the vm primitives reverse map. */
-    static {
-        VM_PRIMITIVES_REVERSE.put(byte.class, "B");
-        VM_PRIMITIVES_REVERSE.put(char.class, "C");
-        VM_PRIMITIVES_REVERSE.put(double.class, "D");
-        VM_PRIMITIVES_REVERSE.put(float.class, "F");
-        VM_PRIMITIVES_REVERSE.put(int.class, "I");
-        VM_PRIMITIVES_REVERSE.put(long.class, "J");
-        VM_PRIMITIVES_REVERSE.put(short.class, "S");
-        VM_PRIMITIVES_REVERSE.put(boolean.class, "Z");
-        VM_PRIMITIVES_REVERSE.put(void.class, "V");
-    }
 
     /**
-     * Get the primitive type for the given VM primitive name.
+     * Map a class object back to a class name.  The returned class object
+     * must be "round trippable", which means
+     * <p/>
+     * type == ClassLoading.loadClass(ClassLoading.getClassName(type), classLoader)
      * <p/>
-     * <p>Mapping:
-     * <pre>
-     *   B - byte
-     *   C - char
-     *   D - double
-     *   F - float
-     *   I - int
-     *   J - long
-     *   S - short
-     *   Z - boolean
-     *   V - void
-     * </pre>
+     * must be true.  To ensure this, the class name is always returned in
+     * method signature format.
      *
-     * @param name VM primitive type name (B, C, J, ...)
-     * @return Primitive type or null.
-     */
-    private static Class getVMPrimitiveType(final String name) {
-        return (Class) VM_PRIMITIVES.get(name);
-    }
-
-    /**
-     * Map of primitive types to their wrapper classes
-     */
-    private static final Map PRIMITIVE_WRAPPERS = new HashMap();
-
-    /** Setup the wrapper map. */
-    static {
-        PRIMITIVE_WRAPPERS.put(Boolean.TYPE, Boolean.class);
-        PRIMITIVE_WRAPPERS.put(Byte.TYPE, Byte.class);
-        PRIMITIVE_WRAPPERS.put(Character.TYPE, Character.class);
-        PRIMITIVE_WRAPPERS.put(Double.TYPE, Double.class);
-        PRIMITIVE_WRAPPERS.put(Float.TYPE, Float.class);
-        PRIMITIVE_WRAPPERS.put(Integer.TYPE, Integer.class);
-        PRIMITIVE_WRAPPERS.put(Long.TYPE, Long.class);
-        PRIMITIVE_WRAPPERS.put(Short.TYPE, Short.class);
-        PRIMITIVE_WRAPPERS.put(Void.TYPE, Void.class);
+     * @param type The class object we convert into name form.
+     * @return A string representation of the class name, in method signature
+     *         format.
+     */
+    public static String getClassName(Class type) {
+        StringBuffer name = new StringBuffer();
+
+        // we test these in reverse order from the resolution steps,
+        // first handling arrays, then primitive types, and finally
+        // "normal" class objects.
+
+        // First handle arrays.  If a class is an array, the type is
+        // element stored at that level.  So, for a 2-dimensional array
+        // of ints, the top-level type will be "[I".  We need to loop
+        // down the hierarchy until we hit a non-array type.
+        while (type.isArray()) {
+            // add another array indicator at the front of the name,
+            // and continue with the next type.
+            name.append('[');
+            type = type.getComponentType();
+        }
+
+        // we're down to the base type.  If this is a primitive, then
+        // we poke in the single-character type specifier.
+        if (type.isPrimitive()) {
+            name.append((String) CLASS_TO_SIGNATURE_MAP.get(type));
+        }
+        // a "normal" class.  This gets expressing using the "Lmy.class.name;" syntax.
+        else {
+            name.append('L');
+            name.append(type.getName());
+            name.append(';');
+        }
+        return name.toString();
+    }
+
+    private static Class getArrayClass(Class type, int dimension) {
+        // Array.newInstance() requires an array of the requested number of dimensions
+        // that gives the size for each dimension.  We just request 0 in each of the
+        // dimentions, which is not unlike a black hole sigularity.
+        int dimensions[] = new int[dimension];
+        // create an instance and return the associated class object.
+        return Array.newInstance(type, dimensions).getClass();
     }
 }
 

Modified: geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/main/CommandLine.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/main/CommandLine.java?rev=290873&r1=290872&r2=290873&view=diff
==============================================================================
--- geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/main/CommandLine.java
(original)
+++ geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/main/CommandLine.java
Wed Sep 21 18:07:45 2005
@@ -34,7 +34,6 @@
 import org.apache.geronimo.kernel.config.ConfigurationUtil;
 import org.apache.geronimo.kernel.config.Configuration;
 import org.apache.geronimo.kernel.log.GeronimoLogging;
-import org.apache.geronimo.system.url.GeronimoURLFactory;
 
 
 /**
@@ -47,9 +46,6 @@
         // This MUST be done before the first log is acquired
         GeronimoLogging.initialize(GeronimoLogging.ERROR);
         log = LogFactory.getLog(CommandLine.class.getName());
-
-        // Install our url factory
-        GeronimoURLFactory.install();
     }
 
     /**

Modified: geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/main/Daemon.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/main/Daemon.java?rev=290873&r1=290872&r2=290873&view=diff
==============================================================================
--- geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/main/Daemon.java (original)
+++ geronimo/trunk/modules/system/src/java/org/apache/geronimo/system/main/Daemon.java Wed
Sep 21 18:07:45 2005
@@ -43,7 +43,6 @@
 import org.apache.geronimo.kernel.log.GeronimoLogging;
 import org.apache.geronimo.system.jmx.MBeanServerKernelBridge;
 import org.apache.geronimo.system.serverinfo.DirectoryUtils;
-import org.apache.geronimo.system.url.GeronimoURLFactory;
 
 /**
  * @version $Rev$ $Date$
@@ -111,9 +110,6 @@
             // This MUST be done before the first log is acquired (WHICH THE STARTUP MONITOR
5 LINES LATER DOES!)
             GeronimoLogging.initialize(verboseArg == null ? GeronimoLogging.WARN : verboseArg
== ARGUMENT_VERBOSE ? GeronimoLogging.INFO : GeronimoLogging.DEBUG);
             log = LogFactory.getLog(Daemon.class.getName());
-
-            // Install our url factory
-            GeronimoURLFactory.install();
         }
 
         if(verboseArg != null || progressArg != null) {

Modified: geronimo/trunk/plugins/maven-geronimo-plugin/src/java/org/apache/geronimo/deployment/mavenplugin/StartServer.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/plugins/maven-geronimo-plugin/src/java/org/apache/geronimo/deployment/mavenplugin/StartServer.java?rev=290873&r1=290872&r2=290873&view=diff
==============================================================================
--- geronimo/trunk/plugins/maven-geronimo-plugin/src/java/org/apache/geronimo/deployment/mavenplugin/StartServer.java
(original)
+++ geronimo/trunk/plugins/maven-geronimo-plugin/src/java/org/apache/geronimo/deployment/mavenplugin/StartServer.java
Wed Sep 21 18:07:45 2005
@@ -36,7 +36,6 @@
 import org.apache.geronimo.kernel.config.Configuration;
 import org.apache.geronimo.kernel.config.InvalidConfigException;
 import org.apache.geronimo.kernel.log.GeronimoLogging;
-import org.apache.geronimo.system.url.GeronimoURLFactory;
 
 /**
  *
@@ -49,9 +48,6 @@
     static {
         // This MUST be done before the first log is acquired
         GeronimoLogging.initialize(GeronimoLogging.INFO);
-
-        // Install our url factory
-        GeronimoURLFactory.install();
     }
 
     private String geronimoHome;



Mime
View raw message