You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mb...@apache.org on 2005/10/27 23:27:51 UTC
svn commit: r328951 - in /incubator/jdo/trunk:
core20/src/java/org/apache/jdo/impl/model/java/
core20/src/java/org/apache/jdo/impl/model/java/reflection/
enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/
fostore20/test/conf/ ri11/src/java/or...
Author: mbo
Date: Thu Oct 27 14:27:16 2005
New Revision: 328951
URL: http://svn.apache.org/viewcvs?rev=328951&view=rev
Log:
Fixed ClassLoader issue in JavaModel implementation.
- Call Class.forName in a doPrivileged block to avoid SecurityException.
- The RuntimeJavaModel delegates a getJavaType lookup to the JavaModel
corresponding to the ClassLoader hat loads the class.
- A getJavaType lookup per Class instance asserts that the specified Class
instance is loaded by the ClassLoader bound to the RuntimeJavaModel instance.
Modified:
incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/BaseReflectionJavaField.java
incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/Bundle.properties
incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModel.java
incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModelFactory.java
incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java
incubator/jdo/trunk/fostore20/test/conf/JDO20Policy
incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java
incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/AbstractJavaModelFactory.java
incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/BaseReflectionJavaField.java
incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/Bundle.properties
incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModel.java
incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModelFactory.java
incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/Bundle.properties
incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModel.java
incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java
incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/xml/XMLExists.java
incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/Bundle.properties
incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModel.java
incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java
Modified: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/BaseReflectionJavaField.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/BaseReflectionJavaField.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/BaseReflectionJavaField.java (original)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/BaseReflectionJavaField.java Thu Oct 27 14:27:16 2005
@@ -165,11 +165,6 @@
catch (NoSuchFieldException ex) {
return null; // do nothing, just return null
}
- catch (LinkageError ex) {
- throw new ModelFatalException(msg.msg(
- "EXC_ClassLoadingError", clazz.getName(), //NOI18N
- ex.toString()));
- }
}
}
);
@@ -197,11 +192,6 @@
throw new ModelFatalException(
msg.msg("EXC_CannotGetDeclaredFields", //NOI18N
clazz.getName()), ex);
- }
- catch (LinkageError ex) {
- throw new ModelFatalException(msg.msg(
- "EXC_ClassLoadingError", clazz.getName(), //NOI18N
- ex.toString()));
}
}
}
Modified: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/Bundle.properties
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/Bundle.properties?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/Bundle.properties (original)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/Bundle.properties Thu Oct 27 14:27:16 2005
@@ -21,11 +21,6 @@
#NOI18N
ERR_InvalidNullFieldInstance={0}: specified Field instance is null.
-
-# {0} - class name
-# {1} - detailed message of the cause
-EXC_ClassLoadingError=Error during loading of class ''{0}'': {1}.
-
#
# BaseReflectionJavaType
#
@@ -75,6 +70,13 @@
must grant ReflectPermission("getClassLoader") to the codeBase containing the \
JavaModel and JDOModel implementation.
+# {0} - class name
+# {1} - class loader
+EXC_CannotGetClassInstance=A SecurityException was thrown when trying to call \
+Class.forName for class ''{0}'' and class loader ''{1}''. In order to get \
+runtime metadata, you must grant ReflectPermission("getClassLoader") to the \
+codeBase containing the JavaModel and JDOModel implementation.
+
# {0} - key instance
EXC_InvalidJavaModelKey=Invalid key for runtime JavaModel lookup: \
expected ''java.lang.ClassLoader'' instance, found ''{0}'' instance.
@@ -87,6 +89,18 @@
EXC_InvalidJavaType=Invalid JavaType instance for getJavaClass method: \
expected ''org.apache.jdo.impl.model.java.ReflectionJavaType'' instance, \
found ''{0}'' instance.
+
+#
+# ReflectionJavaModel
+#
+
+# {0} - class name
+# {1} - class loader of class instance
+# {2} - class loader of JavaModel
+#NOI18N
+ERR_UnexpectedClassLoader=Unexpected class loader. The specified class \
+instance of class ''{0}'' was loaded by class loader ''{1}'', but the \
+JavaModel instance is bound to a different class loader ''{2}''.
#
# ReflectionJavaTypeIntrospector
Modified: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModel.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModel.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModel.java (original)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModel.java Thu Oct 27 14:27:16 2005
@@ -22,11 +22,9 @@
import org.apache.jdo.impl.model.java.AbstractJavaModel;
import org.apache.jdo.impl.model.jdo.caching.JDOModelFactoryImplCaching;
-import org.apache.jdo.model.ModelFatalException;
import org.apache.jdo.model.java.JavaType;
import org.apache.jdo.model.jdo.JDOModel;
import org.apache.jdo.model.jdo.JDOModelFactory;
-import org.apache.jdo.util.I18NHelper;
/**
* A reflection based JavaModel implementation used at runtime.
@@ -37,9 +35,8 @@
* The ReflectionJavaModel implementation will use this ClassLoader to lookup
* any type by name. This makes sure that the type name is unique.
*
- * @author Michael Bouschen
- * @since JDO 1.1
- * @version JDO 2.0
+ * @since 1.1
+ * @version 2.0
*/
public class ReflectionJavaModel
extends AbstractJavaModel
@@ -47,30 +44,15 @@
/** The ClassLoader instance used as key to cache this JavaModel. */
private final ClassLoader classLoader;
- /** Flag passed to the Class.forName call. */
- private final boolean initialize;
-
/** The declaring JavaModelFactory. */
protected final ReflectionJavaModelFactory declaringJavaModelFactory;
- /** I18N support */
- private final static I18NHelper msg =
- I18NHelper.getInstance("org.apache.jdo.impl.model.java.Bundle"); //NOI18N
-
- /** Constructor. */
- public ReflectionJavaModel(ClassLoader classLoader,
- ReflectionJavaModelFactory declaringJavaModelFactory)
- {
- this(classLoader, true, declaringJavaModelFactory);
- }
-
/** Constructor. */
- protected ReflectionJavaModel(ClassLoader classLoader, boolean initialize,
+ protected ReflectionJavaModel(ClassLoader classLoader,
ReflectionJavaModelFactory declaringJavaModelFactory)
{
super();
this.classLoader = classLoader;
- this.initialize = initialize;
this.declaringJavaModelFactory = declaringJavaModelFactory;
}
@@ -92,20 +74,14 @@
JavaType javaType = (JavaType)types.get(name);
if (javaType == null) {
try {
- // Note, if name denotes a pc class that has not been
- // loaded, Class.forName will load the class which
- // calls RegisterClassListener.registerClass.
- // This will create a new JavaType entry in the cache.
- javaType = getJavaTypeInternal(
- Class.forName(name, initialize, classLoader));
+ final boolean initialize = false;
+ Class clazz = ReflectionJavaModelFactory.forNamePrivileged(
+ name, initialize, classLoader);
+ javaType = getJavaTypeInternal(clazz);
}
catch (ClassNotFoundException ex) {
// cannot find class => return null
}
- catch (LinkageError ex) {
- throw new ModelFatalException(msg.msg(
- "EXC_ClassLoadingError", name, ex.toString())); //NOI18N
- }
}
return javaType;
}
@@ -118,32 +94,15 @@
* between this method and getJavaType taking a type name is that this
* method is supposed to return a non-<code>null<code> value. The
* specified class object describes an existing type.
- * <p>
- * Note, this implementation does not call the overloaded getJavaType
- * method taking a String, because this would retrieve the Class
- * instance for the specified type again. Instead, it checks the cache
- * directly. If not available it creates a new ReflectionJavaType using
- * the specified class instance.
* @param clazz the Class instance representing the type
* @return a JavaType instance for the name of the specified class
- * object or <code>null</code> if not present in this model instance.
+ * object.
*/
public JavaType getJavaType(Class clazz)
{
if (clazz == null)
return null;
- if (initialize) {
- try {
- // make sure the class is initialized
- Class.forName(clazz.getName(), initialize,
- ReflectionJavaModelFactory.getClassLoaderPrivileged(clazz));
- }
- catch (ClassNotFoundException ex) {
- // ignore, since class has already been loaded
- }
- }
-
return getJavaTypeInternal(clazz);
}
@@ -168,7 +127,9 @@
return (InputStream) AccessController.doPrivileged(
new PrivilegedAction () {
public Object run () {
- return classLoader.getResourceAsStream(resourceName);
+ ClassLoader loader = (classLoader == null) ?
+ ClassLoader.getSystemClassLoader() : classLoader;
+ return loader.getResourceAsStream(resourceName);
}
}
);
@@ -207,7 +168,7 @@
* @return a JavaType instance for the name of the specified class
* object or <code>null</code> if not present in this model instance.
*/
- protected JavaType getJavaTypeInternal(Class clazz)
+ public JavaType getJavaTypeInternal(Class clazz)
{
String name = clazz.getName();
synchronized (types) {
@@ -219,8 +180,12 @@
return javaType;
}
}
-
- /** */
+
+ /**
+ * Returns the declaring ReflectionJavaModelFactory of this
+ * ReflectionJavaModel.
+ * @return the declaring ReflectionJavaModelFactory
+ */
public ReflectionJavaModelFactory getDeclaringJavaModelFactory()
{
return declaringJavaModelFactory;
Modified: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModelFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModelFactory.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModelFactory.java (original)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModelFactory.java Thu Oct 27 14:27:16 2005
@@ -18,6 +18,8 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import org.apache.jdo.model.ModelException;
import org.apache.jdo.model.ModelFatalException;
@@ -34,8 +36,7 @@
* metadata about types and fields. This implementation caches JavaModel
* instances per ClassLoader.
*
- * @author Michael Bouschen
- * @since JDO 1.1
+ * @since 1.1
*/
public abstract class ReflectionJavaModelFactory
extends AbstractJavaModelFactory
@@ -49,8 +50,7 @@
* use the specified key when caching the new JavaModel instance.
* <p>
* This implementation only accepts <code>java.lang.ClassLoader</code>
- * instances as key and does not support <code>null</code> keys. A
- * ModelException indicates an invalid key.
+ * instances as key. A ModelException indicates an invalid key.
* <p>
* The method automatically sets the parent/child relationship for the
* created JavaModel according to the parent/child relationship of the
@@ -59,22 +59,21 @@
* instance.
* @return a new JavaModel instance.
* @exception ModelException if impossible; the key is of an
- * inappropriate type or the key is <code>null</code> and this
- * JavaModelFactory does not support <code>null</code> keys.
+ * inappropriate type.
*/
public JavaModel createJavaModel(Object key)
throws ModelException
{
- if ((key == null) || (!(key instanceof ClassLoader)))
+ if ((key != null) && (!(key instanceof ClassLoader)))
throw new ModelException(msg.msg("EXC_InvalidJavaModelKey", //NOI18N
- (key==null?"null":key.getClass().getName()))); //NOI18N
+ key.getClass().getName()));
ClassLoader classLoader = (ClassLoader)key;
JavaModel javaModel = newJavaModelInstance(classLoader);
// check parent <-> child relationship
- if (classLoader != ClassLoader.getSystemClassLoader()) {
- // if the specified classLoader is not the system class loader
+ if (classLoader != null) {
+ // if the specified classLoader is not null,
// try to get the parent class loader and update the parent property
try {
ClassLoader parentClassLoader = classLoader.getParent();
@@ -91,20 +90,6 @@
}
/**
- * Returns the JavaModel instance for the specified key.
- * @param key the key used to cache the returned JavaModel instance
- */
- public JavaModel getJavaModel(Object key)
- {
- if (key == null) {
- // null classLoader might happen for classes loaded by the
- // bootstrap class loder
- key = ClassLoader.getSystemClassLoader();
- }
- return super.getJavaModel(key);
- }
-
- /**
* Returns a JavaType instance for the specified type description
* (optional operation). This method is a convenience method and a
* short cut for <code>getJavaModel(key).getJavaType(typeName)</code>.
@@ -138,10 +123,11 @@
// ===== Methods not defined in JavaModelFactory =====
/**
- * Calls getClassLoader on the specified class instance in a
+ * Calls getClassLoader on the specified Class instance in a
* doPrivileged block. Any SecurityException is wrapped into a
* ModelFatalException.
- * @return the class loader that loaded the specified class instance.
+ * @param clazz the class to get the ClassLoader from.
+ * @return the class loader that loaded the specified Class instance.
* @exception ModelFatalException wraps the SecurityException thrown by
* getClassLoader.
*/
@@ -162,6 +148,41 @@
catch (SecurityException ex) {
throw new ModelFatalException(
msg.msg("EXC_CannotGetClassLoader", clazz), ex); //NOI18N
+ }
+ }
+
+ /**
+ * Calls Class.forName in a doPrivileged block. Any SecurityException is
+ * wrapped into a ModelFatalException.
+ * @param name fully qualified name of the desired class
+ * @param initialize whether the class must be initialized
+ * @param loader class loader from which the class must be loaded
+ * @return class object representing the desired class.
+ * @exception ModelFatalException wraps the SecurityException thrown by
+ * getClassLoader.
+ * @exception ClassNotFoundException if the class cannot be located by the
+ * specified class loader.
+ */
+ public static Class forNamePrivileged(final String name,
+ final boolean initialize,
+ final ClassLoader loader)
+ throws ClassNotFoundException
+ {
+ try {
+ return (Class) AccessController.doPrivileged(
+ new PrivilegedExceptionAction () {
+ public Object run () throws ClassNotFoundException {
+ return Class.forName(name, initialize, loader);
+ }
+ }
+ );
+ }
+ catch (PrivilegedActionException pae) {
+ throw (ClassNotFoundException) pae.getException();
+ }
+ catch (SecurityException ex) {
+ throw new ModelFatalException(
+ msg.msg("EXC_CannotGetClassInstance", name, loader), ex);
}
}
Modified: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java (original)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java Thu Oct 27 14:27:16 2005
@@ -43,7 +43,7 @@
public EnhancerJavaModel(ClassLoader classLoader,
ResourceLocator locator)
{
- super(classLoader, false, null);
+ super(classLoader, null);
this.locator = locator;
}
Modified: incubator/jdo/trunk/fostore20/test/conf/JDO20Policy
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/test/conf/JDO20Policy?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/fostore20/test/conf/JDO20Policy (original)
+++ incubator/jdo/trunk/fostore20/test/conf/JDO20Policy Thu Oct 27 14:27:16 2005
@@ -33,6 +33,9 @@
// Allow jdori classes to get metadata for persistence-capable classes.
permission javax.jdo.spi.JDOPermission "getMetadata";
+ // Allow jdo model classes to get a class loader
+ permission java.lang.RuntimePermission "getClassLoader";
+
// Allow jdori classes to access declared members of a class
// (e.g. a query accessing transient instances or non-managed fields).
// The query component needs access to persistent fields.
Modified: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java (original)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java Thu Oct 27 14:27:16 2005
@@ -43,7 +43,7 @@
public EnhancerJavaModel(ClassLoader classLoader,
ResourceLocator locator)
{
- super(classLoader, false);
+ super(classLoader, null);
this.locator = locator;
}
Modified: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/AbstractJavaModelFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/AbstractJavaModelFactory.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/AbstractJavaModelFactory.java (original)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/AbstractJavaModelFactory.java Thu Oct 27 14:27:16 2005
@@ -32,9 +32,7 @@
/**
* Abstract super class for JavaModelFactory implementations. It provides a
* JavaModel cache and implements the JavaModel lookup method
- * {@link #getJavaModel(Object key)}. Any JavaModel instance returned by
- * this method is automatically connected to its corresponding JDOModel
- * instance.
+ * {@link #getJavaModel(Object key)}.
* <p>
* A non-abstract subclass must implement method
* {@link #createJavaModel(Object key)}. The lookup method calls this
@@ -46,7 +44,8 @@
* ModelFatalException.
*
* @author Michael Bouschen
- * @since JDO 1.0.1
+ * @since 1.0.1
+ * @version 1.1
*/
abstract public class AbstractJavaModelFactory
implements JavaModelFactory
@@ -97,7 +96,7 @@
*/
public JavaModel getJavaModel(Object key)
{
- synchronized (this.modelCache) {
+ synchronized (modelCache) {
JavaModel javaModel = (JavaModel)modelCache.get(key);
if (javaModel == null) {
// create new model and store it using the specified key
@@ -107,7 +106,7 @@
}
catch (ModelException ex) {
throw new ModelFatalException(
- "EXC_CannotCreateJavaModel", ex); //NOI18N
+ msg.msg("EXC_CannotCreateJavaModel"), ex); //NOI18N
}
}
return javaModel;
Modified: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/BaseReflectionJavaField.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/BaseReflectionJavaField.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/BaseReflectionJavaField.java (original)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/BaseReflectionJavaField.java Thu Oct 27 14:27:16 2005
@@ -145,11 +145,6 @@
catch (NoSuchFieldException ex) {
return null; // do nothing, just return null
}
- catch (LinkageError ex) {
- throw new ModelFatalException(msg.msg(
- "EXC_ClassLoadingError", clazz.getName(), //NOI18N
- ex.toString()));
- }
}
}
);
Modified: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/Bundle.properties
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/Bundle.properties?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/Bundle.properties (original)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/Bundle.properties Thu Oct 27 14:27:16 2005
@@ -22,10 +22,6 @@
ERR_InvalidNullFieldInstance={0}: specified Field instance is null.
-# {0} - class name
-# {1} - detailed message of the cause
-EXC_ClassLoadingError=Error during loading of class ''{0}'': {1}.
-
#
# BaseReflectionJavaType
#
@@ -64,6 +60,8 @@
# {1} - method name
EXC_MethodNotSupported=Class {0} does not support method {1}.
+EXC_CannotCreateJavaModel=Problems during JavaModel creation.
+
#
# ReflectionJavaModelFactory
#
@@ -73,4 +71,12 @@
class loader of class instance ''{0}''. In order to get runtime metadata, you \
must grant ReflectPermission("getClassLoader") to the codeBase containing the \
JDO Reference Implementation (jdori.jar).
+
+# {0} - class name
+# {1} - class loader
+EXC_CannotGetClassInstance=A SecurityException was thrown when trying to call \
+Class.forName for class ''{0}'' and class loader ''{1}''. In order to get \
+runtime metadata, you must grant ReflectPermission("getClassLoader") to the \
+codeBase containing the JDO Reference Implementation (jdori.jar).
+
Modified: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModel.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModel.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModel.java (original)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModel.java Thu Oct 27 14:27:16 2005
@@ -21,10 +21,8 @@
import java.io.InputStream;
import org.apache.jdo.impl.model.java.AbstractJavaModel;
-import org.apache.jdo.model.ModelFatalException;
import org.apache.jdo.model.java.JavaType;
import org.apache.jdo.model.jdo.JDOModel;
-import org.apache.jdo.util.I18NHelper;
/**
* A reflection based JavaModel implementation used at runtime.
@@ -35,8 +33,7 @@
* The ReflectionJavaModel implementation will use this ClassLoader to lookup
* any type by name. This makes sure that the type name is unique.
*
- * @author Michael Bouschen
- * @since JDO 1.1
+ * @since 1.1
*/
public abstract class ReflectionJavaModel
extends AbstractJavaModel
@@ -44,25 +41,16 @@
/** The ClassLoader instance used as key to cache this JavaModel. */
private final ClassLoader classLoader;
- /** Flag passed to the Class.forName call. */
- private final boolean initialize;
+ /** The declaring JavaModelFactory. */
+ protected final ReflectionJavaModelFactory declaringJavaModelFactory;
- /** I18N support */
- private final static I18NHelper msg =
- I18NHelper.getInstance("org.apache.jdo.impl.model.java.Bundle"); //NOI18N
-
- /** Constructor taking the ClassLoader. */
- public ReflectionJavaModel(ClassLoader classLoader)
- {
- this(classLoader, true);
- }
-
- /** */
- protected ReflectionJavaModel(ClassLoader classLoader, boolean initialize)
+ /** Constructor. */
+ public ReflectionJavaModel(ClassLoader classLoader,
+ ReflectionJavaModelFactory declaringJavaModelFactory)
{
super();
this.classLoader = classLoader;
- this.initialize = initialize;
+ this.declaringJavaModelFactory = declaringJavaModelFactory;
}
/**
@@ -83,20 +71,14 @@
JavaType javaType = (JavaType)types.get(name);
if (javaType == null) {
try {
- // Note, if name denotes a pc class that has not been
- // loaded, Class.forName will load the class which
- // calls RegisterClassListener.registerClass.
- // This will create a new JavaType entry in the cache.
- javaType = getJavaTypeInternal(
- Class.forName(name, initialize, classLoader));
+ final boolean initialize = false;
+ Class clazz = ReflectionJavaModelFactory.forNamePrivileged(
+ name, initialize, classLoader);
+ javaType = getJavaTypeInternal(clazz);
}
catch (ClassNotFoundException ex) {
// cannot find class => return null
}
- catch (LinkageError ex) {
- throw new ModelFatalException(msg.msg(
- "EXC_ClassLoadingError", name, ex.toString())); //NOI18N
- }
}
return javaType;
}
@@ -109,32 +91,15 @@
* between this method and getJavaType taking a type name is that this
* method is supposed to return a non-<code>null<code> value. The
* specified class object describes an existing type.
- * <p>
- * Note, this implementation does not call the overloaded getJavaType
- * method taking a String, because this would retrieve the Class
- * instance for the specified type again. Instead, it checks the cache
- * directly. If not available it creates a new ReflectionJavaType using
- * the specified class instance.
* @param clazz the Class instance representing the type
* @return a JavaType instance for the name of the specified class
- * object or <code>null</code> if not present in this model instance.
+ * object.
*/
public JavaType getJavaType(Class clazz)
{
if (clazz == null)
return null;
- if (initialize) {
- try {
- // make sure the class is initialized
- Class.forName(clazz.getName(), initialize,
- ReflectionJavaModelFactory.getClassLoaderPrivileged(clazz));
- }
- catch (ClassNotFoundException ex) {
- // ignore, since class has already been loaded
- }
- }
-
return getJavaTypeInternal(clazz);
}
@@ -159,7 +124,9 @@
return (InputStream) AccessController.doPrivileged(
new PrivilegedAction () {
public Object run () {
- return classLoader.getResourceAsStream(resourceName);
+ ClassLoader loader = (classLoader == null) ?
+ ClassLoader.getSystemClassLoader() : classLoader;
+ return loader.getResourceAsStream(resourceName);
}
}
);
@@ -185,7 +152,7 @@
* @return a JavaType instance for the name of the specified class
* object or <code>null</code> if not present in this model instance.
*/
- protected JavaType getJavaTypeInternal(Class clazz)
+ public JavaType getJavaTypeInternal(Class clazz)
{
String name = clazz.getName();
synchronized (types) {
@@ -196,6 +163,16 @@
}
return javaType;
}
+ }
+
+ /**
+ * Returns the declaring ReflectionJavaModelFactory of this
+ * ReflectionJavaModel.
+ * @return the declaring ReflectionJavaModelFactory
+ */
+ public ReflectionJavaModelFactory getDeclaringJavaModelFactory()
+ {
+ return declaringJavaModelFactory;
}
/**
Modified: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModelFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModelFactory.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModelFactory.java (original)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/reflection/ReflectionJavaModelFactory.java Thu Oct 27 14:27:16 2005
@@ -18,19 +18,17 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
-import org.apache.jdo.model.ModelException;
import org.apache.jdo.model.ModelFatalException;
-import org.apache.jdo.model.java.JavaModel;
-import org.apache.jdo.model.java.JavaType;
import org.apache.jdo.impl.model.java.AbstractJavaModelFactory;
-import org.apache.jdo.impl.model.java.BaseReflectionJavaType;
import org.apache.jdo.util.I18NHelper;
/**
* A reflection based JavaModelFactory implementation.
*
- * @since JDO 1.1
+ * @since 1.1
*/
public abstract class ReflectionJavaModelFactory
extends AbstractJavaModelFactory
@@ -42,10 +40,11 @@
// ===== Methods not defined in JavaModelFactory =====
/**
- * Calls getClassLoader on the specified class instance in a
+ * Calls getClassLoader on the specified Class instance in a
* doPrivileged block. Any SecurityException is wrapped into a
* ModelFatalException.
- * @return the class loader that loaded the specified class instance.
+ * @param clazz the class to get the ClassLoader from.
+ * @return the class loader that loaded the specified Class instance.
* @exception ModelFatalException wraps the SecurityException thrown by
* getClassLoader.
*/
@@ -66,6 +65,41 @@
catch (SecurityException ex) {
throw new ModelFatalException(
msg.msg("EXC_CannotGetClassLoader", clazz), ex); //NOI18N
+ }
+ }
+
+ /**
+ * Calls Class.forName in a doPrivileged block. Any SecurityException is
+ * wrapped into a ModelFatalException.
+ * @param name fully qualified name of the desired class
+ * @param initialize whether the class must be initialized
+ * @param loader class loader from which the class must be loaded
+ * @return class object representing the desired class.
+ * @exception ModelFatalException wraps the SecurityException thrown by
+ * getClassLoader.
+ * @exception ClassNotFoundException if the class cannot be located by the
+ * specified class loader.
+ */
+ public static Class forNamePrivileged(final String name,
+ final boolean initialize,
+ final ClassLoader loader)
+ throws ClassNotFoundException
+ {
+ try {
+ return (Class) AccessController.doPrivileged(
+ new PrivilegedExceptionAction () {
+ public Object run () throws ClassNotFoundException {
+ return Class.forName(name, initialize, loader);
+ }
+ }
+ );
+ }
+ catch (PrivilegedActionException pae) {
+ throw (ClassNotFoundException) pae.getException();
+ }
+ catch (SecurityException ex) {
+ throw new ModelFatalException(
+ msg.msg("CannotGetClassInstance", name, loader), ex);
}
}
Modified: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/Bundle.properties
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/Bundle.properties?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/Bundle.properties (original)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/Bundle.properties Thu Oct 27 14:27:16 2005
@@ -43,3 +43,18 @@
#NOI18N
ERR_CannotSetJDOModel=Cannot set JDOModel for JavaModel instance.
+#
+# RuntimeJavaModel
+#
+
+# {0} - class name
+# {1} - detailed message of the cause
+EXC_ClassLoadingError=Error during loading of class ''{0}'': {1}.
+
+# {0} - class name
+# {1} - class loader of class instance
+# {2} - class loader of JavaModel
+#NOI18N
+ERR_UnexpectedClassLoader=Unexpected class loader. The specified class \
+instance of class ''{0}'' was loaded by class loader ''{1}'', but the \
+JavaModel instance is bound to a different class loader ''{2}''.
Modified: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModel.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModel.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModel.java (original)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModel.java Thu Oct 27 14:27:16 2005
@@ -16,11 +16,9 @@
package org.apache.jdo.impl.model.java.runtime;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.io.InputStream;
-
+import org.apache.jdo.impl.model.java.PredefinedType; // for javadoc
import org.apache.jdo.impl.model.java.reflection.ReflectionJavaModel;
+import org.apache.jdo.impl.model.java.reflection.ReflectionJavaModelFactory;
import org.apache.jdo.model.ModelFatalException;
import org.apache.jdo.model.java.JavaType;
import org.apache.jdo.model.jdo.JDOModel;
@@ -35,23 +33,130 @@
* The RuntimeJavaModelFactory caches JavaModel instances per ClassLoader.
* The RuntimeJavaModel implementation will use this ClassLoader to lookup
* any type by name. This makes sure that the type name is unique.
+ * <p>
+ * Any JavaType instance bound to a RuntimeJavaModel instance wraps a class
+ * instance that is loaded by the ClassLoader that corresponds to this
+ * RuntimeJavaModel. The only exception are PredefinedType instances
+ * (see {@link PredefinedType.getPredefinedTypes()} which are present in every
+ * RuntimeJavaModel instance.
*
- * @author Michael Bouschen
- * @since JDO 1.0.1
+ * @since 1.0.1
+ * @version 1.1
*/
public class RuntimeJavaModel
extends ReflectionJavaModel
{
- /** Constructor taking the ClassLoader. */
- public RuntimeJavaModel(ClassLoader classLoader)
+ /** I18N support */
+ private final static I18NHelper msg =
+ I18NHelper.getInstance("org.apache.jdo.impl.model.java.runtime.Bundle"); //NOI18N
+
+ /** Constructor. */
+ public RuntimeJavaModel(ClassLoader classLoader,
+ ReflectionJavaModelFactory declaringJavaModelFactory)
{
- super(classLoader, true);
+ super(classLoader, declaringJavaModelFactory);
}
- /** */
- protected RuntimeJavaModel(ClassLoader classLoader, boolean initialize)
+ /**
+ * The method returns the JavaType instance for the specified type
+ * name. A type name is unique within one JavaModel instance. The
+ * method returns <code>null</code> if this model instance does not
+ * know a type with the specified name.
+ * <p>
+ * Note, this method calls Class.forName with the wrapped ClassLoader,
+ * if it cannot find a JavaType with the specified name in the cache.
+ * @param name the name of the type
+ * @return a JavaType instance for the specified name or
+ * <code>null</code> if not present in this model instance.
+ */
+ public JavaType getJavaType(String name)
+ {
+ synchronized (types) {
+ JavaType javaType = (JavaType)types.get(name);
+ if (javaType == null) {
+ try {
+ // Note, if name denotes a pc class that has not been
+ // loaded, Class.forName will load the class which will
+ // register the runtime metadata at the JDOImplHelper.
+ // This will create a new JavaType entry in the cache.
+ final boolean initialize = true;
+ Class clazz = RuntimeJavaModelFactory.forNamePrivileged(
+ name, initialize, getClassLoader());
+ // Get the class loader of the Class instance
+ ClassLoader loader = RuntimeJavaModelFactory.
+ getClassLoaderPrivileged(clazz);
+ // and get the JavaModel instance for the class loader.
+ RuntimeJavaModel javaModel = (RuntimeJavaModel)
+ declaringJavaModelFactory.getJavaModel(loader);
+ // Delegate the JavaType lookup to the JavaModel instance.
+ javaType = javaModel.getJavaTypeInternal(clazz);
+ }
+ catch (ClassNotFoundException ex) {
+ // cannot find class => return null
+ }
+ catch (LinkageError ex) {
+ throw new ModelFatalException(msg.msg(
+ "EXC_ClassLoadingError", name, ex.toString())); //NOI18N
+ }
+ }
+ return javaType;
+ }
+ }
+
+ /**
+ * The method returns the JavaType instance for the type name of the
+ * specified class object. This is a convenience method for
+ * <code>getJavaType(clazz.getName())</code>. The major difference
+ * between this method and getJavaType taking a type name is that this
+ * method is supposed to return a non-<code>null<code> value. The
+ * specified class object describes an existing type.
+ * <p>
+ * Note, this implementation does not call the overloaded getJavaType
+ * method taking a String, because this would retrieve the Class
+ * instance for the specified type again. Instead, it checks the cache
+ * directly. If not available it creates a new ReflectionJavaType using
+ * the specified Class instance.
+ * @param clazz the Class instance representing the type
+ * @return a JavaType instance for the name of the specified class
+ * object or <code>null</code> if not present in this model instance.
+ */
+ public JavaType getJavaType(Class clazz)
{
- super(classLoader, initialize);
+ if (clazz == null)
+ return null;
+
+ String name = clazz.getName();
+ synchronized (types) {
+ JavaType javaType = (JavaType)types.get(name);
+ if (javaType == null) {
+ // Check whether the specified class object is loaded by the
+ // class loader bound to this JavaModel. Note, we never
+ // execute this check for any PredefinedType instance, because
+ // the cache lookup will always find a JavaType (the cache is
+ // initialized with all PredefinedTypes). The check would
+ // potentially fail for a PredefinedType, because it might be
+ // loaded by a different class loader.
+ ClassLoader loader =
+ RuntimeJavaModelFactory.getClassLoaderPrivileged(clazz);
+ if (loader != getClassLoader()) {
+ throw new ModelFatalException(msg.msg(
+ "ERR_UnexpectedClassLoader", //NOI18N
+ clazz.getName(), loader, getClassLoader()));
+ }
+ try {
+ // Make sure the class is initialized, because this will
+ // register the runtime metadata at the JDOImplHelper.
+ final boolean initialize = true;
+ RuntimeJavaModelFactory.forNamePrivileged(
+ clazz.getName(), initialize, loader);
+ }
+ catch (ClassNotFoundException ex) {
+ // ignore, since class has already been loaded
+ }
+ javaType = getJavaTypeInternal(clazz);
+ }
+ return javaType;
+ }
}
/**
Modified: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java (original)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java Thu Oct 27 14:27:16 2005
@@ -18,7 +18,6 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.lang.reflect.Field;
import javax.jdo.spi.JDOImplHelper;
import javax.jdo.spi.JDOPermission;
@@ -48,8 +47,8 @@
* JDOImplHelper to handle the runtime metadata as generated by the
* enhancer.
*
- * @author Michael Bouschen
- * @since JDO 1.0.1
+ * @since 1.0.1
+ * @version 1.1
*/
public class RuntimeJavaModelFactory
extends ReflectionJavaModelFactory
@@ -60,7 +59,7 @@
/** I18N support */
private final static I18NHelper msg =
- I18NHelper.getInstance("org.apache.jdo.impl.model.java.runtime.Bundle"); //NOI18N
+ I18NHelper.getInstance(RuntimeJavaModelFactory.class);
/** */
static
@@ -127,8 +126,7 @@
* use the specified key when caching the new JavaModel instance.
* <p>
* This implementation only accepts <code>java.lang.ClassLoader</code>
- * instances as key and does not support <code>null</code> keys. A
- * ModelException indicates an invalid key.
+ * instances as key. A ModelException indicates an invalid key.
* <p>
* The method automatically sets the parent/child relationship for the
* created JavaModel according to the parent/child relationship of the
@@ -137,28 +135,23 @@
* instance.
* @return a new JavaModel instance.
* @exception ModelException if impossible; the key is of an
- * inappropriate type or the key is <code>null</code> and this
- * JavaModelFactory does not support <code>null</code> keys.
+ * inappropriate type.
*/
public JavaModel createJavaModel(Object key)
throws ModelException
{
- if ((key == null) || (!(key instanceof ClassLoader)))
+ if ((key != null) && (!(key instanceof ClassLoader)))
throw new ModelException(msg.msg("EXC_InvalidJavaModelKey", //NOI18N
- (key==null?"null":key.getClass().getName())));
+ key.getClass().getName()));
ClassLoader classLoader = (ClassLoader)key;
- JavaModel javaModel = new RuntimeJavaModel(classLoader);
+ JavaModel javaModel = new RuntimeJavaModel(classLoader, this);
// check parent <-> child relationship
- if (classLoader != ClassLoader.getSystemClassLoader()) {
- // if the specified classLoader is not the system class loader
- // try to get the parent class loader and update the parent property
+ if (classLoader != null) {
try {
ClassLoader parentClassLoader = classLoader.getParent();
- if (parentClassLoader != null) {
- javaModel.setParent(getJavaModel(parentClassLoader));
- }
+ javaModel.setParent(getJavaModel(parentClassLoader));
}
catch (SecurityException ex) {
// ignore => parentClassLoader and parent JavaModel are null
@@ -171,20 +164,6 @@
return javaModel;
}
- /**
- * Returns the JavaModel instance for the specified key.
- * @param key the key used to cache the returned JavaModel instance
- */
- public JavaModel getJavaModel(Object key)
- {
- if (key == null) {
- // null classLoader might happen for classes loaded by the
- // bootstrap class loder
- key = ClassLoader.getSystemClassLoader();
- }
- return super.getJavaModel(key);
- }
-
/**
* Returns a JavaType instance for the specified type description
* (optional operation). This method is a convenience method and a
Modified: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/xml/XMLExists.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/xml/XMLExists.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/xml/XMLExists.java (original)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/xml/XMLExists.java Thu Oct 27 14:27:16 2005
@@ -18,7 +18,7 @@
import java.util.*;
-import org.apache.jdo.impl.model.java.AbstractJavaModelFactory;
+import org.apache.jdo.impl.model.java.reflection.ReflectionJavaModelFactory;
import org.apache.jdo.impl.model.java.runtime.RuntimeJavaModel;
import org.apache.jdo.impl.model.jdo.caching.JDOModelFactoryImplCaching;
import org.apache.jdo.impl.model.jdo.util.PrintSupport;
@@ -268,18 +268,18 @@
* generated metadata.
*/
private static class XMLExistsJDOModelFactory
- extends AbstractJavaModelFactory {
+ extends ReflectionJavaModelFactory {
/** */
protected XMLExistsJDOModelFactory() {}
/** */
public JavaModel createJavaModel(Object key) throws ModelException {
- if ((key == null) || (!(key instanceof ClassLoader)))
+ if ((key != null) && (!(key instanceof ClassLoader)))
throw new ModelException("Invalid key " + key +
" expected ClassLoader");
ClassLoader classLoader = (ClassLoader)key;
- JavaModel javaModel = new RuntimeJavaModel(classLoader);
+ JavaModel javaModel = new RuntimeJavaModel(classLoader, this);
// set the JDOModel property in JavaModel
setJDOModelInternal(javaModel);
Modified: incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/Bundle.properties
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/Bundle.properties?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/Bundle.properties (original)
+++ incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/Bundle.properties Thu Oct 27 14:27:16 2005
@@ -28,6 +28,22 @@
codeBases containing the JDO API and the JavaModel and JDOModel implementation.
#
+# RuntimeJavaModel
+#
+
+# {0} - class name
+# {1} - detailed message of the cause
+EXC_ClassLoadingError=Error during loading of class ''{0}'': {1}.
+
+# {0} - class name
+# {1} - class loader of class instance
+# {2} - class loader of JavaModel
+#NOI18N
+ERR_UnexpectedClassLoader=Unexpected class loader. The specified class \
+instance of class ''{0}'' was loaded by class loader ''{1}'', but the \
+JavaModel instance is bound to a different class loader ''{2}''.
+
+#
# RuntimeJavaType
#
@@ -36,3 +52,8 @@
# {2} - field name
#NOI18N
ERR_MultipleJavaField={0}: multiple JavaField ''{1}'' for class ''{2}''.
+
+# {0} - class name
+# {1} - detailed message of the cause
+EXC_ClassLoadingError=Error during loading of class ''{0}'': {1}.
+
Modified: incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModel.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModel.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModel.java (original)
+++ incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModel.java Thu Oct 27 14:27:16 2005
@@ -16,8 +16,11 @@
package org.apache.jdo.impl.model.java.runtime;
+import org.apache.jdo.impl.model.java.PredefinedType; // for javadoc
import org.apache.jdo.impl.model.java.reflection.ReflectionJavaModel;
+import org.apache.jdo.model.ModelFatalException;
import org.apache.jdo.model.java.JavaType;
+import org.apache.jdo.util.I18NHelper;
/**
* A reflection based JavaModel implementation used at runtime.
@@ -28,21 +31,132 @@
* The RuntimeJavaModelFactory caches JavaModel instances per ClassLoader.
* The RuntimeJavaModel implementation will use this ClassLoader to lookup
* any type by name. This makes sure that the type name is unique.
+ * <p>
+ * Any JavaType instance bound to a RuntimeJavaModel instance wraps a class
+ * instance that is loaded by the ClassLoader that corresponds to this
+ * RuntimeJavaModel. The only exception are PredefinedType instances
+ * (see {@link PredefinedType.getPredefinedTypes()} which are present in every
+ * RuntimeJavaModel instance.
*
- * @author Michael Bouschen
- * @since JDO 1.0.1
- * @version JDO 2.0
+ * @since 1.0.1
+ * @version 2.0
*/
public class RuntimeJavaModel
extends ReflectionJavaModel
{
+ /** I18N support */
+ private final static I18NHelper msg =
+ I18NHelper.getInstance("org.apache.jdo.impl.model.java.runtime.Bundle"); //NOI18N
+
/** Constructor. */
public RuntimeJavaModel(ClassLoader classLoader,
RuntimeJavaModelFactory declaringJavaModelFactory)
{
super(classLoader, declaringJavaModelFactory);
}
-
+
+ /**
+ * The method returns the JavaType instance for the specified type
+ * name. A type name is unique within one JavaModel instance. The
+ * method returns <code>null</code> if this model instance does not
+ * know a type with the specified name.
+ * <p>
+ * Note, this method calls Class.forName with the wrapped ClassLoader,
+ * if it cannot find a JavaType with the specified name in the cache.
+ * @param name the name of the type
+ * @return a JavaType instance for the specified name or
+ * <code>null</code> if not present in this model instance.
+ */
+ public JavaType getJavaType(String name)
+ {
+ synchronized (types) {
+ JavaType javaType = (JavaType)types.get(name);
+ if (javaType == null) {
+ try {
+ // Note, if name denotes a pc class that has not been
+ // loaded, Class.forName will load the class which will
+ // register the runtime metadata at the JDOImplHelper.
+ // This will create a new JavaType entry in the cache.
+ final boolean initialize = true;
+ Class clazz = RuntimeJavaModelFactory.forNamePrivileged(
+ name, initialize, getClassLoader());
+ // Get the class loader of the Class instance
+ ClassLoader loader = RuntimeJavaModelFactory.
+ getClassLoaderPrivileged(clazz);
+ // and get the JavaModel instance for the class loader.
+ RuntimeJavaModel javaModel = (RuntimeJavaModel)
+ declaringJavaModelFactory.getJavaModel(loader);
+ // Delegate the JavaType lookup to the JavaModel instance.
+ javaType = javaModel.getJavaTypeInternal(clazz);
+ }
+ catch (ClassNotFoundException ex) {
+ // cannot find class => return null
+ }
+ catch (LinkageError ex) {
+ throw new ModelFatalException(msg.msg(
+ "EXC_ClassLoadingError", name, ex.toString())); //NOI18N
+ }
+ }
+ return javaType;
+ }
+ }
+
+ /**
+ * The method returns the JavaType instance for the type name of the
+ * specified class object. This is a convenience method for
+ * <code>getJavaType(clazz.getName())</code>. The major difference
+ * between this method and getJavaType taking a type name is that this
+ * method is supposed to return a non-<code>null<code> value. The
+ * specified class object describes an existing type.
+ * <p>
+ * Note, this implementation does not call the overloaded getJavaType
+ * method taking a String, because this would retrieve the Class
+ * instance for the specified type again. Instead, it checks the cache
+ * directly. If not available it creates a new ReflectionJavaType using
+ * the specified Class instance.
+ * @param clazz the Class instance representing the type
+ * @return a JavaType instance for the name of the specified class
+ * object or <code>null</code> if not present in this model instance.
+ */
+ public JavaType getJavaType(Class clazz)
+ {
+ if (clazz == null)
+ return null;
+
+ String name = clazz.getName();
+ synchronized (types) {
+ JavaType javaType = (JavaType)types.get(name);
+ if (javaType == null) {
+ // Check whether the specified class object is loaded by the
+ // class loader bound to this JavaModel. Note, we never
+ // execute this check for any PredefinedType instance, because
+ // the cache lookup will always find a JavaType (the cache is
+ // initialized with all PredefinedTypes). The check would
+ // potentially fail for a PredefinedType, because it might be
+ // loaded by a different class loader.
+ ClassLoader loader =
+ RuntimeJavaModelFactory.getClassLoaderPrivileged(clazz);
+ if (loader != getClassLoader()) {
+ throw new ModelFatalException(msg.msg(
+ "ERR_UnexpectedClassLoader", //NOI18N
+ clazz.getName(), loader, getClassLoader()));
+ }
+ try {
+ // Make sure the class is initialized, because this will
+ // register the runtime metadata at the JDOImplHelper.
+ final boolean initialize = true;
+ RuntimeJavaModelFactory.forNamePrivileged(
+ clazz.getName(), initialize, loader);
+ }
+ catch (ClassNotFoundException ex) {
+ // ignore, since class has already been loaded
+ }
+ javaType = getJavaTypeInternal(clazz);
+ }
+ return javaType;
+ }
+ }
+
/**
* Creates a new instance of the JavaType implementation class.
* <p>
Modified: incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java?rev=328951&r1=328950&r2=328951&view=diff
==============================================================================
--- incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java (original)
+++ incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java Thu Oct 27 14:27:16 2005
@@ -41,9 +41,8 @@
* JDOImplHelper to handle the runtime metadata as generated by the
* enhancer.
*
- * @author Michael Bouschen
- * @since JDO 1.0.1
- * @version JDO 2.0
+ * @since 1.0.1
+ * @version 2.0
*/
public class RuntimeJavaModelFactory
extends ReflectionJavaModelFactory