1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.jdo.impl.model.java.reflection;
19
20 import java.security.AccessController;
21 import java.security.PrivilegedAction;
22 import java.io.InputStream;
23
24 import org.apache.jdo.impl.model.java.AbstractJavaModel;
25 import org.apache.jdo.impl.model.jdo.caching.JDOModelFactoryImplCaching;
26 import org.apache.jdo.model.java.JavaType;
27 import org.apache.jdo.model.jdo.JDOModel;
28 import org.apache.jdo.model.jdo.JDOModelFactory;
29
30 /***
31 * A reflection based JavaModel implementation used at runtime.
32 * The implementation takes <code>java.lang.Class</code> and
33 * <code>java.lang.reflect.Field</code> instances to get Java related
34 * metadata about types and fields.
35 * <p>
36 * The ReflectionJavaModel implementation will use this ClassLoader to lookup
37 * any type by name. This makes sure that the type name is unique.
38 *
39 * @since 1.1
40 * @version 2.0
41 */
42 public class ReflectionJavaModel
43 extends AbstractJavaModel
44 {
45 /*** The ClassLoader instance used as key to cache this JavaModel. */
46 private final ClassLoader classLoader;
47
48 /*** The declaring JavaModelFactory. */
49 protected final ReflectionJavaModelFactory declaringJavaModelFactory;
50
51 /*** Constructor. */
52 protected ReflectionJavaModel(ClassLoader classLoader,
53 ReflectionJavaModelFactory declaringJavaModelFactory)
54 {
55 super();
56 this.classLoader = classLoader;
57 this.declaringJavaModelFactory = declaringJavaModelFactory;
58 }
59
60 /***
61 * The method returns the JavaType instance for the specified type
62 * name. A type name is unique within one JavaModel instance. The
63 * method returns <code>null</code> if this model instance does not
64 * know a type with the specified name.
65 * <p>
66 * Note, this method calls Class.forName with the wrapped ClassLoader,
67 * if it cannot find a JavaType with the specified name in the cache.
68 * @param name the name of the type
69 * @return a JavaType instance for the specified name or
70 * <code>null</code> if not present in this model instance.
71 */
72 public JavaType getJavaType(String name)
73 {
74 synchronized (types) {
75 JavaType javaType = (JavaType)types.get(name);
76 if (javaType == null) {
77 try {
78 final boolean initialize = false;
79 Class clazz = ReflectionJavaModelFactory.forNamePrivileged(
80 name, initialize, classLoader);
81 javaType = getJavaTypeInternal(clazz);
82 }
83 catch (ClassNotFoundException ex) {
84
85 }
86 }
87 return javaType;
88 }
89 }
90
91 /***
92 * The method returns the JavaType instance for the type name of the
93 * specified class object. This is a convenience method for
94 * <code>getJavaType(clazz.getName())</code>. The major difference
95 * between this method and getJavaType taking a type name is that this
96 * method is supposed to return a non-<code>null<code> value. The
97 * specified class object describes an existing type.
98 * @param clazz the Class instance representing the type
99 * @return a JavaType instance for the name of the specified class
100 * object.
101 */
102 public JavaType getJavaType(Class clazz)
103 {
104 if (clazz == null)
105 return null;
106
107 return getJavaTypeInternal(clazz);
108 }
109
110 /***
111 * Finds a resource with a given name. A resource is some data that can
112 * be accessed by class code in a way that is independent of the
113 * location of the code. The name of a resource is a "/"-separated path
114 * name that identifies the resource. The method method opens the
115 * resource for reading and returns an InputStream. It returns
116 * <code>null</code> if no resource with this name is found or if the
117 * caller doesn't have adequate privileges to get the resource.
118 * <p>
119 * This implementation delegates the request to the wrapped
120 * ClassLoader.
121 * @param resourceName the resource name
122 * @return an input stream for reading the resource, or <code>null</code>
123 * if the resource could not be found or if the caller doesn't have
124 * adequate privileges to get the resource.
125 */
126 public InputStream getInputStreamForResource(final String resourceName)
127 {
128 return (InputStream) AccessController.doPrivileged(
129 new PrivilegedAction () {
130 public Object run () {
131 ClassLoader loader = (classLoader == null) ?
132 ClassLoader.getSystemClassLoader() : classLoader;
133 return loader.getResourceAsStream(resourceName);
134 }
135 }
136 );
137 }
138
139 /***
140 * Returns the corresponding JDOModel instance.
141 * @return the corresponding JDOModel.
142 */
143 public JDOModel getJDOModel()
144 {
145 if (jdoModel == null) {
146 JDOModelFactory factory = JDOModelFactoryImplCaching.getInstance();
147 jdoModel = factory.getJDOModel(this);
148 }
149 return jdoModel;
150 }
151
152
153
154 /***
155 * Returns the ClassLoader wrapped by this ReflectionJavaModel instance.
156 * @return the ClassLoader
157 */
158 public ClassLoader getClassLoader()
159 {
160 return classLoader;
161 }
162
163 /***
164 * The method returns the JavaType instance for the type name of the
165 * specified class object. It first checks the cache and if there is no
166 * entry for the type name in the cache then it creates a new JavaType
167 * instance for the specified Class object.
168 * @param clazz the Class instance representing the type
169 * @return a JavaType instance for the name of the specified class
170 * object or <code>null</code> if not present in this model instance.
171 */
172 public JavaType getJavaTypeInternal(Class clazz)
173 {
174 String name = clazz.getName();
175 synchronized (types) {
176 JavaType javaType = (JavaType)types.get(name);
177 if (javaType == null) {
178 javaType = newJavaTypeInstance(clazz);
179 types.put(name, javaType);
180 }
181 return javaType;
182 }
183 }
184
185 /***
186 * Returns the declaring ReflectionJavaModelFactory of this
187 * ReflectionJavaModel.
188 * @return the declaring ReflectionJavaModelFactory
189 */
190 public ReflectionJavaModelFactory getDeclaringJavaModelFactory()
191 {
192 return declaringJavaModelFactory;
193 }
194
195 /***
196 * Creates a new instance of the JavaType implementation class.
197 * <p>
198 * This implementation returns a ReflectionJavaType instance.
199 * @param clazz the Class instance representing the type
200 * @return a new JavaType instance
201 */
202 protected JavaType newJavaTypeInstance(Class clazz)
203 {
204 return new ReflectionJavaType(clazz, this);
205 }
206
207 }