FileDocCategorySizeDatePackage
RuntimeModel.javaAPI DocGlassfish v2 API28515Fri May 04 22:34:42 BST 2007com.sun.jdo.api.persistence.model

RuntimeModel

public class RuntimeModel extends Model
author
raccah
version
%I%

Fields Summary
private static final String
CLASS_EXTENSION
Extension of the class file, used to figure out the path for handling the mapping file.
private static final String
JAVA_PACKAGE
Constant which represents the prefix of the java package.
private static final String
SERIALIZABLE
Constant which represents the serializable interface.
private HashMap
classLoaders
Map of class loader used to find classes and mapping information. Keys are fully qualified class names.
Constructors Summary
protected RuntimeModel()
Creates a new RuntimeModel. This constructor should not be called directly; instead, the static instance accesible from the Model class should be used.

see
Model#RUNTIME

	
	                           	 
	  
	
		super();
	
Methods Summary
protected java.io.BufferedOutputStreamcreateFile(java.lang.String className, java.lang.String baseFileName, java.lang.String extension)
Creates a file with the given base file name and extension parallel to the supplied class (if it does not yet exist).

param
className the fully qualified name of the class
param
baseFileName the name of the base file
param
extension the file extension
return
the output stream for the specified resource, null if an error occurs or none exists
exception
IOException if there is some error creating the file

		char extensionCharacter = '.";
		File file = getFile(className, 
			baseFileName + extensionCharacter + extension);

		if (file == null)
		{
			Class classElement = (Class)getClass(className);

			if (classElement != null)
			{
				// need to find the path before the package name
				String path = classElement.getResource(
					getShortClassName(className) + extensionCharacter + 
					CLASS_EXTENSION).getFile();
				int index = path.lastIndexOf(extensionCharacter) + 1;
				
				file = new File(path.substring(0, index) + extension);
				file.createNewFile();
			}
		}
		return ((file != null)
                ? (new BufferedOutputStream(new FileOutputStream(file)))
                : null);
	
protected voiddeleteFile(java.lang.String className, java.lang.String fileName)
Deletes the file with the given file name which is parallel to the supplied class.

param
className the fully qualified name of the class
param
fileName the name of the file
exception
IOException if there is some error deleting the file

		File file = getFile(className, fileName);

		if ((file != null) && file.exists())
			file.delete();
	
protected java.lang.ClassLoaderfindClassLoader(java.lang.String className, java.lang.ClassLoader classLoader)
This method returns the class loader used to find mapping information for the specified className. If the classLoader argument is not null, the method updates the classLoaders cache and returns the specified classLoader. Otherwise it checks the cache for the specified className and returns this class loader. If there is no cached class loader it returns the current class loader.

param
className the fully qualified name of the class to be checked
param
classLoader the class loader used to find mapping information
return
the class loader used to find mapping information for the specified className
exception
IllegalArgumentException if there is class loader problem

		ClassLoader cached = null;

		if (className == null)
			return null;
		else if (className.startsWith(JAVA_PACKAGE) || isPrimitive(className))
			// Use current class loader for java packages or primitive types
			// - these classes cannot have the multiple class loader conflict
			// - these classes should not show up in the classLoaders map
			return getClass().getClassLoader();

		synchronized (classLoaders)
		{
			cached = (ClassLoader)classLoaders.get(className);

			if (classLoader == null)
			{
				// Case 1: specified class loader is null =>
				// return cached class loader if available, if not
				// take current class loader
				classLoader =
					(cached != null) ? cached : getClass().getClassLoader();
			}
			else if (cached == null)
			{
				// Case 2: specified class loader is NOT null AND
				// no class loader cached for the class name =>
				// put specified class loader in cache
				classLoaders.put(className, classLoader);
			}
			else if (classLoader != cached)
			{
				// Case 3: specified class loader is NOT null AND
				// cache contains class loader for this class name AND
				// both class loaders are not identical =>
				// pontential conflict
				Class clazz = null;
				Class cachedClazz  = null;

				try
				{
					String prop = ClassLoaderStrategy.getStrategy();

					// Load the class using specified and cached class loader.
					// NOTE, do not change the order of the next two lines, the
					// catch block relies on it!
					clazz = Class.forName(className, true, classLoader);
					cachedClazz = Class.forName(className, true, cached);

					if (clazz.getClassLoader() == cachedClazz.getClassLoader())
					{
						// Case 3a: both class loaders are the same =>
						// return it
						return cached;
					}
					else if (ClassLoaderStrategy.MULTIPLE_CLASS_LOADERS_IGNORE.equals(prop))
					{
						// Case 3b: both class loaders are different and
						// the system property is defined as ignore =>
						// ignore the specified class loader and return
						// the cached class loader
						return cached;
					}
					else if (ClassLoaderStrategy.MULTIPLE_CLASS_LOADERS_RELOAD.equals(prop))
					{
						// Case 3c: both class loaders are different and
						// the system property is defined as reload =>
						// discard the cached class loader and replace it
						// by the specified class loader
						removeResourcesFromCaches(cachedClazz.getClassLoader());
						classLoaders.put(className, classLoader);
						return classLoader;
					}
					else
					{
						// Case 3d: both class loaders are different and
						// the system property is defined as error or
						// any other value =>
						// throw exception
						throw new IllegalArgumentException(I18NHelper.getMessage(
							getMessages(), "classloader.multiple", // NOI18N
							className));
					}
				}
				catch (ClassNotFoundException ex)
				{
					// At least one of the class loader could not find the class.
					// Update the classLoader map, if the specified class loader
					// could find it, but the cached could not.
					if ((clazz != null) && (cachedClazz == null))
						classLoaders.put(className, classLoader);
				}
			}
		}

		return classLoader;
	
protected java.lang.StringfindPenultimateSuperclass(java.lang.String className)
Returns the name of the second to top (top excluding java.lang.Object) superclass for the given class name.

param
className the fully qualified name of the class to be checked
return
the top non-Object superclass for className, className if an error occurs or none exists

		Class classElement = (Class)getClass(className);
		Class objectClass = java.lang.Object.class;
		Class testClass = null;

		if (classElement == null)
			return className;

		while ((testClass = classElement.getSuperclass()) != null)
		{
			if (testClass.equals(objectClass))
				break;

			classElement = testClass;
		}

		return classElement.getName();
	
public java.lang.ObjectgetClass(java.lang.String className, java.lang.ClassLoader classLoader)
Returns the class element with the specified className. The class is found using Class.forName.

param
className the fully qualified name of the class to be checked
param
classLoader the class loader used to find mapping information
return
the class element for the specified className, null if an error occurs or none exists

		if (className == null) 
			return null;
		
		try
		{
			classLoader = findClassLoader(className, classLoader);
			return Class.forName(className, true, classLoader);
		}
		catch (ClassNotFoundException e)
		{
			return null;
		}
	
public java.util.MapgetClassLoaderCache()
Returns an unmodifiable copy of the ClassLoader cache.

return
unmodifiable ClassLoader cache

		return Collections.unmodifiableMap(classLoaders);
	
public java.lang.ObjectgetConstructor(java.lang.String className, java.lang.String[] argTypeNames)
Returns the constructor element for the specified argument types in the class with the specified name. Types are specified as type names for primitive type such as int, float or as fully qualified class names.

param
className the name of the class which contains the constructor to be checked
param
argTypeNames the fully qualified names of the argument types
return
the constructor element
see
#getClass

		final Class classElement = (Class)getClass(className);

		if (classElement != null)
		{
			final Class[] argTypes = getTypesForNames(argTypeNames);

			return AccessController.doPrivileged(new PrivilegedAction()
			{
				public Object run ()
				{
					try
					{  
						return ((Class)classElement).getDeclaredConstructor(
							argTypes);
					}
					catch (NoSuchMethodException ex)
					{
						// constructor not found => return null
						return null;
					}
				}
			});
		}

		return null;
	
public java.lang.StringgetDeclaringClass(java.lang.Object memberElement)
Returns the string representation of declaring class of the specified member element. Note, the member element is either a class element as returned by getClass, a field element as returned by getField, a constructor element as returned by getConstructor, or a method element as returned by getMethod executed on the same model instance. This implementation expects the member element to be a reflection instance.

param
memberElement the member element to be checked
return
the string representation of the declaring class of the specified memberElement
see
#getClass
see
#getField
see
#getConstructor
see
#getMethod

		Class classElement = null;

		if ((memberElement != null) && (memberElement instanceof Member))
			classElement = ((Member)memberElement).getDeclaringClass();

		return ((classElement != null) ? classElement.getName() : null);
	
public java.lang.ObjectgetField(java.lang.String className, java.lang.String fieldName)
Returns the field element for the specified fieldName in the class with the specified className.

param
className the fully qualified name of the class which contains the field to be checked
param
fieldName the name of the field to be checked
return
the field element for the specified fieldName

		final Class classElement = (Class)getClass(className);

		if (classElement != null)
		{
			return AccessController.doPrivileged(new PrivilegedAction()
			{
				public Object run ()
				{
					try
					{
						return classElement.getDeclaredField(fieldName);
					}
					catch (NoSuchFieldException e)
					{
						// field not found => return null;
						return null;
					}
				}
			});
		}

		return null;
	
public java.util.ListgetFields(java.lang.String className)
Returns a list of names of all the declared field elements in the class with the specified name.

param
className the fully qualified name of the class to be checked
return
the names of the field elements for the specified class

		List returnList = new ArrayList();
		final Class classElement = (Class)getClass(className);
		
		if (classElement != null)
		{
			Field[] fields = (Field[]) AccessController.doPrivileged(
				new PrivilegedAction()
			{
				public Object run ()
				{
					return classElement.getDeclaredFields();
				}
			});
			int i, count = fields.length;

			for (i = 0; i < count; i++)
				returnList.add(fields[i].getName());
		}

		return returnList;
	
protected java.io.FilegetFile(java.lang.String className, java.lang.String fileName)
Returns a file with the given file name which is parallel to the supplied class.

param
className the fully qualified name of the class
param
fileName the name of the file
return
the file object for the specified resource, null if an error occurs
exception
IOException if there is some error getting the file

		Class classElement = (Class)getClass(className);

		if (classElement != null)
		{
			// need to find the path before the package name
			URL path = classElement.getResource(fileName.substring(
				fileName.lastIndexOf(getShortClassName(className))));

			return ((path != null) ? (new File(path.getFile())) : null);
		}

		return null;
	
protected java.io.BufferedInputStreamgetInputStreamForResource(java.lang.String className, java.lang.ClassLoader classLoader, java.lang.String resourceName)
Returns the input stream with the supplied resource name found with the supplied class name. NOTE, this implementation assumes the specified class loader is not null and needs not to be validated. Any validation is done by getMappingClass which is the only caller of this method.

param
className the fully qualified name of the class which will be used as a base to find the resource
param
classLoader the class loader used to find mapping information
param
resourceName the name of the resource to be found
return
the input stream for the specified resource, null if an error occurs or none exists

		InputStream is = ((className != null) ? 
                          classLoader.getResourceAsStream(resourceName) : null);

        BufferedInputStream rc = null;
        if (is != null && !(is instanceof BufferedInputStream)) {
            rc = new BufferedInputStream(is);
        } else {
            rc = (BufferedInputStream)is;
        }
        return rc;
	
public com.sun.jdo.api.persistence.model.mapping.MappingClassElementgetMappingClass(java.lang.String className, java.lang.ClassLoader classLoader)
Returns the MappingClassElement created for the specified class name. This method looks up the class in the internal cache. If not present it loads the corresponding xml file containing the mapping information.

param
className the fully qualified name of the mapping class
param
classLoader the class loader used to find mapping information
return
the MappingClassElement for className, null if an error occurs or none exists
see
MappingClassElementImpl#forName

		MappingClassElement mappingClass = null;

		// First check class loader. This has to be done before the super call!
		// Method Model.getMappingClass will check the MappingClassElement cache
		// and will find an entry in the case of a multiple class loader for the
		// same class name. So we have to check the multiple class loader first.
		classLoader = findClassLoader(className, classLoader);
		mappingClass = super.getMappingClass(className, classLoader);
		if ((mappingClass != null) && (classLoader != null))
		{
			// Lookup the SchemElement connected to mappingClass. This reads 
			// the .dbschema file using the specified classLoader and stores the
			// SchemaElement in the SchemaElement cache. Any subsequent 
			// SchemaElement.forName or TableElement.forName lookups will use 
			// the cached version.
			String databaseRoot = mappingClass.getDatabaseRoot();

			// An unmapped mapping class is allowed in which case the 
			// databaseRoot will be null (never mapped) or empty 
			// (mapped once, unmapped now), but if the databaseRoot is 
			// not null or empty and we can't find the schema, throw a 
			// RuntimeException to notify the user that something is wrong.
			if (!StringHelper.isEmpty(databaseRoot) && 
				(SchemaElement.forName(databaseRoot, classLoader) == null))
			{
				throw new RuntimeException(I18NHelper.getMessage(
					getMessages(), "dbschema.not_found", // NOI18N
					databaseRoot, className)); 
			}
		}
	
		return mappingClass;
	
public java.lang.ObjectgetMethod(java.lang.String className, java.lang.String methodName, java.lang.String[] argTypeNames)
Returns the method element for the specified method name and argument types in the class with the specified name. Types are specified as type names for primitive type such as int, float or as fully qualified class names. Note, the method does not return inherited methods.

param
className the name of the class which contains the method to be checked
param
methodName the name of the method to be checked
param
argTypeNames the fully qualified names of the argument types
return
the method element
see
#getClass

		final Class classElement = (Class)getClass(className);

		if (classElement != null)
		{
			final Class[] argTypes =  getTypesForNames(argTypeNames);

			return AccessController.doPrivileged(new PrivilegedAction()
			{
				public Object run ()
				{
					try
					{
						return classElement.getDeclaredMethod(
							methodName, argTypes);
					}
					catch (NoSuchMethodException ex)
					{
						// method not found => return null
						return null;
					}
				}
			});
		}

		return null;
	
public intgetModifiers(java.lang.Object memberElement)
Returns the modifier mask for the specified member element. Note, the member element is either a class element as returned by getClass, a field element as returned by getField, a constructor element as returned by getConstructor, or a method element as returned by getMethod executed on the same model instance. This implementation expects the member element to be a reflection instance.

param
memberElement the member element to be checked
return
the modifier mask for the specified memberElement
see
java.lang.reflect.Modifier
see
#getClass
see
#getField
see
#getConstructor
see
#getMethod

		int modifiers = 0;
		
		if (memberElement != null) 
		{
			if (memberElement instanceof Class)
			{
				modifiers = ((Class)memberElement).getModifiers();
			}
			else if (memberElement instanceof Member)
			{
				modifiers = ((Member)memberElement).getModifiers();
			}
		}

		return modifiers;
	
private java.lang.StringgetNameForType(java.lang.Class type)

		String typeName = null;

		if (type != null)
		{
			if (type.isArray())
			{
				typeName = getNameForType(
					type.getComponentType()) + "[]";	// NOI18N
			}
			else
				typeName = type.getName();
		}

		return typeName;
	
private java.lang.StringgetShortClassName(java.lang.String className)
Computes the class name (without package) for the supplied class name.

param
className the fully qualified name of the class
return
the class name (without package) for the supplied class name

		 return JavaTypeHelper.getShortClassName(className);
	
protected java.lang.StringgetSuperclass(java.lang.String className)
Returns the name of the superclass for the given class name.

param
className the fully qualified name of the class to be checked
return
the superclass for className, null if an error occurs or none exists

		Class classElement = (Class)getClass(className);

		if (classElement != null)
			classElement = classElement.getSuperclass();

		return ((classElement != null) ? classElement.getName() : null);
	
public java.lang.StringgetType(java.lang.Object element)
Returns the string representation of type of the specified element. If element denotes a field, it returns the type of the field. If element denotes a method, it returns the return type of the method. Note, element is either a field element as returned by getField, or a method element as returned by getMethod executed on the same model instance. This implementation expects the element being a reflection instance.

param
element the element to be checked
return
the string representation of the type of the element
see
#getField
see
#getMethod

		return getNameForType(getTypeObject(element));
	
private java.lang.ClassgetTypeForName(java.lang.String typeName)
Converts the specified type name into its corresponding java.lang.Class representation.

		Class clazz = JavaTypeHelper.getPrimitiveClass(typeName);

		if (clazz == null)
			clazz = (Class)getClass(typeName);

		return clazz;
	
protected java.lang.ClassgetTypeObject(java.lang.Object element)
Returns the Class type of the specified element. If element denotes a field, it returns the type of the field. If element denotes a method, it returns the return type of the method. Note, element is either a field element as returned by getField, or a method element as returned by getMethod executed on the same model instance.

param
element the element to be checked
return
the Class type of the element
see
#getField
see
#getMethod

		Class type = null;

		if (element != null)
		{
			if (element instanceof Field)
				type = ((Field)element).getType();
			else if (element instanceof Method)
				type = ((Method)element).getReturnType();
		}

		return type;
	
private java.lang.Class[]getTypesForNames(java.lang.String[] typeNames)
Converts the array of type names into an array of Class objects.

		Class[] classes = new Class[typeNames.length];

		for (int i = 0; i < classes.length; i++)
			classes[i] = getTypeForName(typeNames[i]);

		return classes;
	
public booleanhasConstructor(java.lang.String className)
Determines if the class with the specified name declares a constructor.

param
className the name of the class to be checked
return
true if the class declares a constructor; false otherwise.
see
#getClass

		final Class classElement = (Class)getClass(className);

		if (classElement != null)
		{
			Boolean b = (Boolean)AccessController.doPrivileged(
				new PrivilegedAction()
			{
				public Object run ()
				{
					return JavaTypeHelper.valueOf(((Class)classElement).
						getDeclaredConstructors().length != 0);
				}
			});

			return b.booleanValue();
		}

		return false;
	
public booleanimplementsInterface(java.lang.Object classElement, java.lang.String interfaceName)
Determines if the specified class implements the specified interface. Note, class element is a model specific class representation as returned by a getClass call executed on the same model instance. This implementation expects the class element being a reflection instance.

param
classElement the class element to be checked
param
interfaceName the fully qualified name of the interface to be checked
return
true if the class implements the interface; false otherwise.
see
#getClass

		Class interfaceClass = (Class)getClass(interfaceName);

		if ((classElement == null) || !(classElement instanceof Class) ||
			(interfaceClass == null))
			return false;
		
		return interfaceClass.isAssignableFrom((Class)classElement);
	
public booleanisArray(java.lang.String className, java.lang.String fieldName)
Determines if a field with the specified fieldName in the class with the specified className is an array.

param
className the fully qualified name of the class which contains the field to be checked
param
fieldName the name of the field to be checked
return
true if this field name represents a java array field; false otherwise.
see
#getFieldType

		Object fieldElement = getField(className, fieldName);

		return ((fieldElement != null) ? 
			getTypeObject(fieldElement).isArray() : false);
	
public booleanisInterface(java.lang.String className)
Determines if the specified className represents an interface type.

param
className the fully qualified name of the class to be checked
return
true if this class name represents an interface; false otherwise.

		Class classElement = (Class)getClass(className);
	
		return ((classElement != null) ? classElement.isInterface() : false);
	
public booleanisSerializable(java.lang.Object fieldElement)
Determines if the specified field element has a serializable type. A type is serializable if it is a primitive type, a class that implements java.io.Serializable or an interface that inherits from java.io.Serializable. Note, the field element is a model specific field representation as returned by a getField call executed on the same model instance. This implementation expects the field element being a reflection instance.

param
fieldElement the field element to be checked
return
true if the field element has a serializable type; false otherwise.
see
#getField

		Class type = getTypeObject(fieldElement);

		// check if the topmost element type is serializable
		while ((type != null) && type.isArray())
			type = type.getComponentType();

		return ((type != null) ? 
			(type.isPrimitive() || implementsInterface(type, SERIALIZABLE)) : 
			false);
	
public voidremoveResourcesFromCaches(java.lang.ClassLoader classLoader)
Removes the classes cached with the specified class loader from all caches. The method iterates the ClassLoader cache to find classes cached with the specified class loader. These classes are removed from the ClassLoader cache, the cache of MappingClassElements and the set of classes known to be non PC. The associated SchemaElements are removed from the SchemaElement cache.

param
classLoader used to determine the classes to be removed

		Collection classNames = new HashSet();

		synchronized(classLoaders)
		{
			for (Iterator i = classLoaders.entrySet().iterator(); i.hasNext();)
			{
				Map.Entry next = (Map.Entry)i.next();

				// check the cached class loader
				if (next.getValue() == classLoader)
				{
					// add className to the collection of classNames to be 
					// removed
					classNames.add(next.getKey());
					// remove this entry from the classLoaders cache
					i.remove();
				}
			}
		}

		removeResourcesFromCaches(classNames);