KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > ejb > cmp3 > base > CMP3Policy


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.ejb.cmp3.base;
23
24 import java.lang.reflect.Field JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.security.AccessController JavaDoc;
27 import java.security.PrivilegedActionException JavaDoc;
28 import java.util.*;
29 import oracle.toplink.essentials.descriptors.*;
30 import oracle.toplink.essentials.internal.helper.ConversionManager;
31 import oracle.toplink.essentials.internal.localization.ExceptionLocalization;
32 import oracle.toplink.essentials.internal.sessions.AbstractSession;
33 import oracle.toplink.essentials.mappings.DatabaseMapping;
34 import oracle.toplink.essentials.mappings.foundation.AbstractDirectMapping;
35 import oracle.toplink.essentials.exceptions.*;
36 import oracle.toplink.essentials.internal.helper.DatabaseField;
37 import oracle.toplink.essentials.internal.descriptors.ObjectBuilder;
38 import oracle.toplink.essentials.internal.security.PrivilegedAccessHelper;
39 import oracle.toplink.essentials.internal.security.PrivilegedGetField;
40 import oracle.toplink.essentials.internal.security.PrivilegedClassForName;
41 import oracle.toplink.essentials.internal.security.PrivilegedGetMethod;
42 import oracle.toplink.essentials.internal.security.PrivilegedGetValueFromField;
43 import oracle.toplink.essentials.internal.security.PrivilegedSetValueInField;
44 import oracle.toplink.essentials.internal.security.PrivilegedMethodInvoker;
45 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataHelper;
46
47 /**
48  * <b>Description</b>: Defines primary key extraction coce,
49  * and differentiates CMP3 from CMP1/2.
50  *
51  * @since TopLink 10.1.3
52  */

53
54 // This should be refactored to have an abstract CMPPolicy, and have CMP1/2/3 subclass and define correct functionality.
55
public class CMP3Policy extends CMPPolicy {
56
57     /** Stores the fields for this classes compound primary key class if required. */
58     protected KeyElementAccessor[] keyClassFields;
59     
60     // Store the primary key class name
61
protected String JavaDoc pkClassName;
62     
63     // Stores the class version of the PKClass
64
protected Class JavaDoc pkClass;
65
66     public CMP3Policy() {
67         super();
68     }
69     
70     /**
71      * INTERNAL:
72      * Convert all the class-name-based settings in this object to actual class-based
73      * settings. This method is used when converting a project that has been built
74      * with class names to a project with classes.
75      * @param classLoader
76      */

77     public void convertClassNamesToClasses(ClassLoader JavaDoc classLoader){
78         if(getPKClassName() != null){
79             try{
80                 Class JavaDoc pkClass = null;
81                 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
82                     try {
83                         pkClass = (Class JavaDoc)AccessController.doPrivileged(new PrivilegedClassForName(getPKClassName(), true, classLoader));
84                     } catch (PrivilegedActionException JavaDoc exception) {
85                         throw new IllegalArgumentException JavaDoc(ExceptionLocalization.buildMessage("pk_class_not_found", new Object JavaDoc[] {this.pkClassName}), exception.getException());
86                         
87                     }
88                 } else {
89                     pkClass = oracle.toplink.essentials.internal.security.PrivilegedAccessHelper.getClassForName(getPKClassName(), true, classLoader);
90                 }
91                 setPKClass(pkClass);
92             } catch (ClassNotFoundException JavaDoc exc){
93                 throw new IllegalArgumentException JavaDoc(ExceptionLocalization.buildMessage("pk_class_not_found", new Object JavaDoc[] {this.pkClassName}), exc);
94             }
95         }
96     }
97
98     /**
99      * INTERNAL:
100      * Return if this policy is for CMP3.
101      */

102     public boolean isCMP3Policy() {
103         return true;
104     }
105     
106     /**
107      * INTERNAL:
108      */

109     public void setPrimaryKeyClassName(String JavaDoc pkClassName) {
110         this.pkClassName = pkClassName;
111     }
112     
113     /**
114      * INTERNAL:
115      */

116     public Class JavaDoc getPKClass() {
117         if(this.pkClass == null && getPKClassName() == null) {
118             initializePrimaryKeyFields(null);
119         }
120         return this.pkClass;
121     }
122
123     /**
124      * ADVANCED:
125      */

126     public void setPKClass(Class JavaDoc pkClass) {
127         this.pkClass = pkClass;
128     }
129
130     /**
131      * INTERNAL:
132      */

133     public String JavaDoc getPKClassName() {
134         return pkClassName;
135     }
136     
137     /**
138      * INTERNAL:
139      */

140     public Object JavaDoc getPKClassInstance() {
141         try {
142             return getPKClass().newInstance();
143         } catch (Exception JavaDoc ex) {
144             return null;
145             // WIP - this should throw an exception
146
}
147     }
148     
149     /**
150      * INTERNAL:
151      * Use the key to create a TopLink primary key Vector.
152      * If the key is simple (direct mapped) then just add it to a vector,
153      * otherwise must go through the inefficient process of copying the key into the bean
154      * and extracting the key from the bean.
155      *
156      * @param key Object the primary key to use for creating the vector
157      * @return Vector
158      */

159     public Vector createPkVectorFromKey(Object JavaDoc key, AbstractSession session) {
160         // If the descriptor primary key is mapped through direct-to-field mappings,
161
// then no elaborate conversion is required.
162
// If key is compound, add each value to the vector.
163
KeyElementAccessor[] pkElementArray = this.getKeyClassFields(key.getClass());
164         Vector pkVector = new Vector(pkElementArray.length);
165         for (int index = 0; index < pkElementArray.length; index++) {
166             DatabaseMapping mapping = this.getDescriptor().getObjectBuilder().getMappingForAttributeName(pkElementArray[index].getAttributeName());
167             if (mapping == null) {
168                 mapping = this.getDescriptor().getObjectBuilder().getMappingForField(pkElementArray[index].getDatabaseField());
169             }
170             while (mapping.isAggregateObjectMapping()) {
171                 mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForAttributeName(pkElementArray[index].getAttributeName());
172                 if (mapping == null) {// must be aggregate
173
mapping = this.getDescriptor().getObjectBuilder().getMappingForField(pkElementArray[index].getDatabaseField());
174                 }
175             }
176             Object JavaDoc fieldValue = null;
177             if (mapping.isDirectToFieldMapping()) {
178                 fieldValue = ((AbstractDirectMapping)mapping).getFieldValue(pkElementArray[index].getValue(key), (oracle.toplink.essentials.internal.sessions.AbstractSession)session);
179             } else {
180                 fieldValue = pkElementArray[index].getValue(key);
181             }
182             pkVector.add(fieldValue);
183         }
184         return pkVector;
185     }
186     
187     /**
188      * INTERNAL:
189      * Create an instance of the composite primary key class for the key object.
190      */

191     public Object JavaDoc createPrimaryKeyInstance(Object JavaDoc key, AbstractSession session) {
192         Object JavaDoc keyInstance = getPKClassInstance();
193         ObjectBuilder builder = getDescriptor().getObjectBuilder();
194         KeyElementAccessor[] pkElementArray = this.getKeyClassFields(getPKClass());
195                 
196         for (int index = 0; index < pkElementArray.length; index++) {
197             KeyElementAccessor accessor = pkElementArray[index];
198             DatabaseMapping mapping = builder.getMappingForAttributeName(accessor.getAttributeName());
199             // With session validation, the mapping shouldn't be null at this
200
// point, don't bother checking.
201

202             while (mapping.isAggregateObjectMapping()) {
203                 mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForAttributeName(pkElementArray[index].getAttributeName());
204             
205                 if (mapping == null) { // must be aggregate
206
mapping = builder.getMappingForField(accessor.getDatabaseField());
207                 }
208             }
209             
210             Object JavaDoc fieldValue = mapping.getRealAttributeValueFromObject(key, (oracle.toplink.essentials.internal.sessions.AbstractSession) session);
211             accessor.setValue(keyInstance, fieldValue);
212         }
213         
214         return keyInstance;
215     }
216     
217
218     /**
219      * INTERNAL:
220      * Use the key to create a bean and initialize its primary key fields.
221      * Note: If is a compound PK then a primary key object is being used.
222      * This method should only be used for 'templates' when executing
223      * queries. The bean built will not be given an EntityContext and should
224      * not be used as an actual entity bean.
225      *
226      * @param key Object the primary key to use for initializing the bean's
227      * corresponding pk fields
228      * @return TopLinkCmpEntity
229      */

230     protected Object JavaDoc createBeanUsingKey(Object JavaDoc key, AbstractSession session) {
231         try {
232             Object JavaDoc bean = this.getDescriptor().getInstantiationPolicy().buildNewInstance();
233             KeyElementAccessor[] keyElements = this.getKeyClassFields(key.getClass());
234             for (int index = 0; index < keyElements.length; ++index) {
235                 Object JavaDoc toWriteInto = bean;
236                 Object JavaDoc keyFieldValue = keyElements[index].getValue(key);
237                 DatabaseField field = keyElements[index].getDatabaseField();
238                 DatabaseMapping mapping = this.getDescriptor().getObjectBuilder().getMappingForAttributeName(keyElements[index].getAttributeName());
239                 if (mapping == null) {// must be aggregate
240
mapping = this.getDescriptor().getObjectBuilder().getMappingForField(field);
241                 }
242                 while (mapping.isAggregateObjectMapping()) {
243                     Object JavaDoc aggregate = mapping.getRealAttributeValueFromObject(toWriteInto, session);
244                     if (aggregate == null) {
245                         aggregate = mapping.getReferenceDescriptor().getJavaClass().newInstance();
246                         mapping.setRealAttributeValueInObject(toWriteInto, aggregate);
247                     }
248                     mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForAttributeName(keyElements[index].getAttributeName());
249                     if (mapping == null) {// must be aggregate
250
mapping = this.getDescriptor().getObjectBuilder().getMappingForField(field);
251                     }
252
253                     //change the object to write into to the aggregate for the next stage of the
254
// loop or for when we exit the loop.
255
toWriteInto = aggregate;
256                 }
257                 mapping.setRealAttributeValueInObject(toWriteInto, keyFieldValue);
258             }
259             return bean;
260         } catch (Exception JavaDoc e) {
261             throw DescriptorException.errorUsingPrimaryKey(key, this.getDescriptor(), e);
262         }
263     }
264
265     /**
266      * INTERNAL:
267      * Cache the bean's primary key fields so speed up creating of primary key
268      * objects and initialization of beans.
269      *
270      * Note, we have to re-look up the fields for the bean class since
271      * these fields may have been loaded with the wrong loader (thank you Kirk).
272      * If the key is compound, we also have to look up the fields for the key.
273      */

274     protected KeyElementAccessor[] initializePrimaryKeyFields(Class JavaDoc keyClass) {
275         KeyElementAccessor[] pkAttributes = null;
276         ClassDescriptor descriptor = this.getDescriptor();
277
278         pkAttributes = new KeyElementAccessor[descriptor.getObjectBuilder().getPrimaryKeyMappings().size()];
279
280         Iterator attributesIter = descriptor.getPrimaryKeyFields().iterator();
281
282         // used fields in case it is an embedded class
283
for (int i = 0; attributesIter.hasNext(); i++) {
284             DatabaseField field = (DatabaseField)attributesIter.next();
285             Vector allMappings = null;
286
287             // this next section looks strange but we need to check all mappings
288
// for this field not just the writable one and instead of having multiple
289
// sections of duplicate code I will jst add the writable mapping to the list.
290
allMappings = descriptor.getObjectBuilder().getReadOnlyMappingsForField(field);
291             if (allMappings == null) {
292                 allMappings = new Vector(1);
293             }
294             allMappings.add(descriptor.getObjectBuilder().getMappingForField(field));
295             Exception JavaDoc elementIsFound = null;// use exception existence to detemine if element was found, so we can throw exception later
296
for (int index = (allMappings.size() - 1); index >= 0; --index) {//start with the writable first
297
DatabaseMapping mapping = (DatabaseMapping)allMappings.get(index);
298                 if (mapping.isAggregateMapping()) {//in the case of aggregates drill down.
299
Vector aggregateMappings = mapping.getReferenceDescriptor().getObjectBuilder().getReadOnlyMappingsForField(field);
300                     if ((aggregateMappings != null) && (!aggregateMappings.isEmpty())) {
301                         //looks weird but must try all of the other aggregate mappings as well.
302
allMappings.add(aggregateMappings);
303                         index = (allMappings.size() - 1);
304                     }
305                     mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(field);
306                 }
307                 String JavaDoc fieldName = mapping.getAttributeName();
308                 if (keyClass == null){
309                     // must be a primitive
310
pkAttributes[i] = new KeyIsElementAccessor(mapping.getAttributeName(), field);
311                     setPKClass(ConversionManager.getObjectClass(mapping.getAttributeClassification()));
312                     elementIsFound = null;
313                 } else {
314                     try {
315                         Field JavaDoc keyField = null;
316                         if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
317                             try {
318                                 keyField = (Field JavaDoc)AccessController.doPrivileged(new PrivilegedGetField(keyClass, fieldName, true));
319                             } catch (PrivilegedActionException JavaDoc exception) {
320                                 throw (NoSuchFieldException JavaDoc)exception.getException();
321                             }
322                         } else {
323                             keyField = PrivilegedAccessHelper.getField(keyClass, fieldName, true);
324                         }
325                         pkAttributes[i] = new FieldAccessor(keyField, fieldName, field);
326                         elementIsFound = null;
327                     } catch (NoSuchFieldException JavaDoc ex) {
328                         //must be a property
329
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
330                         buffer.append("get");
331                         buffer.append(fieldName.substring(0, 1).toUpperCase());
332                         buffer.append(fieldName.substring(1));
333                         try {
334                             Method JavaDoc method = null;
335                             if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
336                                 try {
337                                     method = (Method JavaDoc)AccessController.doPrivileged(new PrivilegedGetMethod(keyClass, buffer.toString(), new Class JavaDoc[] { }, true));
338                                 } catch (PrivilegedActionException JavaDoc exception) {
339                                     throw (NoSuchMethodException JavaDoc)exception.getException();
340                                 }
341                             } else {
342                                 method = PrivilegedAccessHelper.getMethod(keyClass, buffer.toString(), new Class JavaDoc[] { }, true);
343                             }
344                             pkAttributes[i] = new PropertyAccessor(method, fieldName, field);
345                             elementIsFound = null;
346                         } catch (NoSuchMethodException JavaDoc exs) {
347                             // not a field not a method
348
if (descriptor.getObjectBuilder().getPrimaryKeyMappings().size() == 1) {
349                                 //must be a primitive
350
pkAttributes[i] = new KeyIsElementAccessor(mapping.getAttributeName(), field);
351                                 setPKClass(ConversionManager.getObjectClass(mapping.getAttributeClassification()));
352                                 elementIsFound = null;
353                             } else {
354                                 elementIsFound = exs;
355                             }
356                         }
357                     }
358                 }
359                 
360                 if (elementIsFound == null) {
361                     break;// break out of the loop we do not need to look for any more
362
}
363             }
364             if (elementIsFound != null) {
365                 throw DescriptorException.errorUsingPrimaryKey(keyClass, getDescriptor(), elementIsFound);
366             }
367         }
368         return pkAttributes;
369     }
370
371     /**
372      * INTERNAL:
373      * @return Returns the keyClassFields.
374      */

375     protected KeyElementAccessor[] getKeyClassFields(Class JavaDoc clazz) {
376         if (this.keyClassFields == null){
377             this.keyClassFields = initializePrimaryKeyFields(this.pkClass == null? clazz : this.pkClass);
378         }
379         return this.keyClassFields;
380     }
381
382     /**
383      * INTERNAL:
384      * This is the interface used to encapsilate the the type of key class element
385      */

386     private interface KeyElementAccessor {
387         public String JavaDoc getAttributeName();
388         public DatabaseField getDatabaseField();
389         public Object JavaDoc getValue(Object JavaDoc object);
390         public void setValue(Object JavaDoc object, Object JavaDoc value);
391     }
392
393     /**
394      * INTERNAL:
395      * This class is used when the key class element is a property
396      */

397     private class PropertyAccessor implements KeyElementAccessor {
398         protected Method JavaDoc method;
399         protected String JavaDoc attributeName;
400         protected DatabaseField databaseField;
401
402         public PropertyAccessor(Method JavaDoc method, String JavaDoc attributeName, DatabaseField field) {
403             this.method = method;
404             this.attributeName = attributeName;
405             this.databaseField = field;
406         }
407
408         public String JavaDoc getAttributeName() {
409             return this.attributeName;
410         }
411
412         public DatabaseField getDatabaseField() {
413             return this.databaseField;
414         }
415         
416         public Object JavaDoc getValue(Object JavaDoc object) {
417             try {
418                 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
419                     try {
420                         return AccessController.doPrivileged(new PrivilegedMethodInvoker(method, object, new Object JavaDoc[] { }));
421                     } catch (PrivilegedActionException JavaDoc exception) {
422                         Exception JavaDoc throwableException = exception.getException();
423                         if (throwableException instanceof IllegalAccessException JavaDoc) {
424                             throw (IllegalAccessException JavaDoc)throwableException;
425                         } else {
426                             throw (java.lang.reflect.InvocationTargetException JavaDoc)throwableException;
427                         }
428                     }
429                 } else {
430                     return PrivilegedAccessHelper.invokeMethod(method, object, new Object JavaDoc[] { });
431                 }
432             } catch (Exception JavaDoc ex) {
433                 throw DescriptorException.errorUsingPrimaryKey(object, getDescriptor(), ex);
434             }
435         }
436         
437         public void setValue(Object JavaDoc object, Object JavaDoc value) {
438             try {
439                 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
440                     try {
441                         AccessController.doPrivileged(new PrivilegedMethodInvoker(MetadataHelper.getSetMethod(method, object.getClass()), object, new Object JavaDoc[] {value}));
442                     } catch (PrivilegedActionException JavaDoc exception) {
443                         Exception JavaDoc throwableException = exception.getException();
444                         if (throwableException instanceof IllegalAccessException JavaDoc) {
445                             throw (IllegalAccessException JavaDoc)throwableException;
446                         } else {
447                             throw (java.lang.reflect.InvocationTargetException JavaDoc)throwableException;
448                         }
449                     }
450                 } else {
451                     PrivilegedAccessHelper.invokeMethod(MetadataHelper.getSetMethod(method, object.getClass()), object, new Object JavaDoc[] {value});
452                 }
453             } catch (Exception JavaDoc ex) {
454                 throw DescriptorException.errorUsingPrimaryKey(object, getDescriptor(), ex);
455             }
456         }
457     }
458
459     /**
460      * INTERNAL:
461      * This class will be used when the element of the keyclass is a field
462      */

463     private class FieldAccessor implements KeyElementAccessor {
464         protected Field JavaDoc field;
465         protected String JavaDoc attributeName;
466         protected DatabaseField databaseField;
467
468         public FieldAccessor(Field JavaDoc field, String JavaDoc attributeName, DatabaseField databaseField) {
469             this.field = field;
470             this.attributeName = attributeName;
471             this.databaseField = databaseField;
472         }
473
474         public String JavaDoc getAttributeName() {
475             return this.attributeName;
476         }
477
478         public DatabaseField getDatabaseField() {
479             return this.databaseField;
480         }
481         
482         public Object JavaDoc getValue(Object JavaDoc object) {
483             try {
484                 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
485                     try {
486                         return AccessController.doPrivileged(new PrivilegedGetValueFromField(field, object));
487                     } catch (PrivilegedActionException JavaDoc exception) {
488                         throw DescriptorException.errorUsingPrimaryKey(object, getDescriptor(), exception.getException()); }
489                 } else {
490                     return oracle.toplink.essentials.internal.security.PrivilegedAccessHelper.getValueFromField(field, object);
491                 }
492             } catch (Exception JavaDoc ex) {
493                 throw DescriptorException.errorUsingPrimaryKey(object, getDescriptor(), ex);
494             }
495         }
496         
497         public void setValue(Object JavaDoc object, Object JavaDoc value) {
498             try {
499                 Field JavaDoc pkField = null;
500                 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
501                     try {
502                         pkField = (Field JavaDoc)AccessController.doPrivileged(new PrivilegedGetField(object.getClass(), field.getName(), true));
503                         AccessController.doPrivileged(new PrivilegedSetValueInField(pkField, object, value));
504                     } catch (PrivilegedActionException JavaDoc exception) {
505                         throw DescriptorException.errorUsingPrimaryKey(object, getDescriptor(), exception.getException());
506                     }
507                 } else {
508                     pkField = PrivilegedAccessHelper.getField(object.getClass(), field.getName(), true);
509                     PrivilegedAccessHelper.setValueInField(pkField, object, value);
510                 }
511             } catch (Exception JavaDoc ex) {
512                 throw DescriptorException.errorUsingPrimaryKey(object, getDescriptor(), ex);
513             }
514         }
515     }
516
517     /**
518      * INTERNAL:
519      * This class will be used when the keyClass is a primitive
520      */

521     private class KeyIsElementAccessor implements KeyElementAccessor {
522         protected String JavaDoc attributeName;
523         protected DatabaseField databaseField;
524
525         public KeyIsElementAccessor(String JavaDoc attributeName, DatabaseField databaseField) {
526             this.attributeName = attributeName;
527             this.databaseField = databaseField;
528         }
529
530         public String JavaDoc getAttributeName() {
531             return attributeName;
532         }
533
534         public DatabaseField getDatabaseField() {
535             return this.databaseField;
536         }
537         
538         public Object JavaDoc getValue(Object JavaDoc object) {
539             return object;
540         }
541         
542         public void setValue(Object JavaDoc object, Object JavaDoc value) {
543             // WIP - do nothing for now???
544
}
545     }
546 }
547
Popular Tags