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