You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by da...@apache.org on 2005/09/22 03:08:05 UTC
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/...
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;