1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.betwixt.io.read;
18
19 import java.beans.IntrospectionException;
20 import java.lang.reflect.Constructor;
21
22 import org.apache.commons.betwixt.ElementDescriptor;
23 import org.apache.commons.betwixt.XMLBeanInfo;
24 import org.apache.commons.logging.Log;
25
26
27
28
29
30
31
32
33 public class ChainedBeanCreatorFactory {
34
35 private static final Class[] EMPTY_CLASS_ARRAY = {};
36 private static final Object[] EMPTY_OBJECT_ARRAY = {};
37
38
39 private static final ChainedBeanCreator derivedBeanCreator
40 = new ChainedBeanCreator() {
41 public Object create(
42 ElementMapping elementMapping,
43 ReadContext context,
44 BeanCreationChain chain) {
45
46 Log log = context.getLog();
47 String className
48 = elementMapping
49 .getAttributes().getValue( context.getClassNameAttribute() );
50 if ( className != null ) {
51 try {
52
53 ClassLoader classLoader = context.getClassLoader();
54 Class clazz = null;
55 if ( classLoader == null ) {
56 log.warn("Read context classloader not set." );
57 } else {
58 try
59 {
60 clazz = classLoader.loadClass( className );
61 } catch (ClassNotFoundException e) {
62 log.info("Class not found in context classloader:");
63 log.debug(clazz, e);
64 }
65 }
66 if (clazz == null) {
67 clazz = Class.forName(className);
68 }
69 return newInstance(clazz, log);
70
71 } catch (Exception e) {
72
73 log.warn( "Could not create instance of type: " + className );
74 log.debug( "Create new instance failed: ", e );
75 return null;
76 }
77
78 } else {
79
80 return chain.create( elementMapping, context );
81 }
82 }
83 };
84
85
86
87
88
89
90 public static final ChainedBeanCreator createDerivedBeanCreator() {
91 return derivedBeanCreator;
92 }
93
94
95
96
97
98
99
100
101
102 private static final Object newInstance(Class theClass, Log log) throws Exception {
103 Object result = null;
104 try {
105 Constructor constructor = theClass.getConstructor(EMPTY_CLASS_ARRAY);
106 if (!constructor.isAccessible()) {
107 constructor.setAccessible(true);
108 }
109 result = constructor.newInstance(EMPTY_OBJECT_ARRAY);
110 } catch (SecurityException e) {
111 log.debug("Cannot force accessibility to constructor", e);
112
113 } catch (NoSuchMethodException e) {
114 if (log.isDebugEnabled()) {
115 log.debug("Class " + theClass + " has no empty constructor.");
116 }
117 }
118
119 if (result == null) {
120 result = theClass.newInstance();
121 }
122 return result;
123 }
124
125
126 private static final ChainedBeanCreator elementTypeBeanCreator
127 = new ChainedBeanCreator() {
128 public Object create(
129 ElementMapping element,
130 ReadContext context,
131 BeanCreationChain chain) {
132
133 Log log = context.getLog();
134 Class theClass = null;
135
136 ElementDescriptor descriptor = element.getDescriptor();
137 if ( descriptor != null ) {
138
139 theClass = context.resolvePolymorphicType(element);
140
141 if (theClass == null)
142 {
143
144 theClass = descriptor.getImplementationClass();
145 }
146 }
147
148 if ( theClass == null ) {
149
150 theClass = element.getType();
151 }
152
153 if (descriptor != null && descriptor.isPolymorphic()) {
154
155 try {
156 XMLBeanInfo xmlBeanInfo = context.getXMLIntrospector().introspect(theClass);
157 String namespace = element.getNamespace();
158 String name = element.getName();
159 if (namespace == null) {
160 if (!name.equals(xmlBeanInfo.getElementDescriptor().getQualifiedName())) {
161 context.getLog().debug("Polymorphic type does not match element");
162 return null;
163 }
164 } else if (!namespace.equals(xmlBeanInfo.getElementDescriptor().getURI())
165 || !name.equals(xmlBeanInfo.getElementDescriptor().getLocalName())) {
166 context.getLog().debug("Polymorphic type does not match element");
167 return null;
168 }
169 } catch (IntrospectionException e) {
170 context.getLog().warn(
171 "Could not introspect type to test introspection: " + theClass.getName() );
172 context.getLog().debug( "Introspection failed: ", e );
173 return null;
174 }
175
176 }
177
178 if ( log.isTraceEnabled() ) {
179 log.trace(
180 "Creating instance of class " + theClass.getName()
181 + " for element " + element.getName());
182 }
183
184 try {
185
186 Object result = newInstance(theClass, log);
187 return result;
188
189 } catch (Exception e) {
190
191 context.getLog().warn(
192 "Could not create instance of type: " + theClass.getName() );
193 context.getLog().debug( "Create new instance failed: ", e );
194 return null;
195 }
196 }
197 };
198
199
200
201
202
203 public static final ChainedBeanCreator createElementTypeBeanCreator() {
204 return elementTypeBeanCreator;
205 }
206
207
208 private static final ChainedBeanCreator idRefBeanCreator
209 = new ChainedBeanCreator() {
210 public Object create(
211 ElementMapping elementMapping,
212 ReadContext context,
213 BeanCreationChain chain) {
214 if ( context.getMapIDs() ) {
215 String idref = elementMapping.getAttributes().getValue( "idref" );
216 if ( idref != null ) {
217
218
219
220
221 context.getLog().trace( "Found IDREF" );
222 Object bean = context.getBean( idref );
223 if ( bean != null ) {
224 if ( context.getLog().isTraceEnabled() ) {
225 context.getLog().trace( "Matched bean " + bean );
226 }
227 return bean;
228 }
229 context.getLog().trace( "No match found" );
230 }
231 }
232 return chain.create( elementMapping, context );
233 }
234 };
235
236
237
238
239
240 public static final ChainedBeanCreator createIDREFBeanCreator() {
241 return idRefBeanCreator;
242 }
243 }