KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > jdo > spi > JDOImplHelper


1 /*
2  * Copyright 2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 /*
18  * JDOImplHelper.java
19  *
20  */

21
22 package javax.jdo.spi;
23
24 import java.lang.reflect.Constructor JavaDoc;
25
26 import java.text.DateFormat JavaDoc;
27 import java.text.ParsePosition JavaDoc;
28 import java.text.SimpleDateFormat JavaDoc;
29
30 import java.util.ArrayList JavaDoc;
31 import java.util.Collection JavaDoc;
32 import java.util.Collections JavaDoc;
33 import java.util.Currency JavaDoc;
34 import java.util.Date JavaDoc;
35 import java.util.HashMap JavaDoc;
36 import java.util.HashSet JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.List JavaDoc;
39 import java.util.Locale JavaDoc;
40 import java.util.Map JavaDoc;
41 import java.util.WeakHashMap JavaDoc;
42
43 import javax.jdo.JDOException;
44 import javax.jdo.JDOFatalInternalException;
45 import javax.jdo.JDOFatalUserException;
46 import javax.jdo.JDOUserException;
47 import javax.jdo.spi.JDOPermission;
48
49 /** This class is a helper class for JDO implementations. It contains methods
50  * to register metadata for persistence-capable classes and to perform common
51  * operations needed by implementations, not by end users.
52  * <P><code>JDOImplHelper</code> allows construction of instances of persistence-capable
53  * classes without using reflection.
54  * <P>Persistence-capable classes register themselves via a static method
55  * at class load time.
56  * There is no security restriction on this access. JDO implementations
57  * get access to the functions provided by this class only if they are
58  * authorized by the security manager. To avoid having every call go through
59  * the security manager, only the call to get an instance is checked. Once an
60  * implementation
61  * has an instance, any of the methods can be invoked without security checks.
62  * @version 1.0.2
63  *
64  */

65 public class JDOImplHelper extends java.lang.Object JavaDoc {
66     
67     /** This synchronized <code>HashMap</code> contains a static mapping of
68      * <code>PersistenceCapable</code> class to
69      * metadata for the class used for constructing new instances. New entries
70      * are added by the static method in each <code>PersistenceCapable</code> class.
71      * Entries are never removed.
72      */

73     private static Map JavaDoc registeredClasses = Collections.synchronizedMap(new HashMap JavaDoc ());
74     
75     /** This Set contains all classes that have registered for setStateManager
76      * permissions via authorizeStateManagerClass.
77      */

78     private static Map JavaDoc authorizedStateManagerClasses = new WeakHashMap JavaDoc();
79
80     /** This list contains the registered listeners for <code>RegisterClassEvent</code>s.
81      */

82     private static List JavaDoc listeners = new ArrayList JavaDoc();
83
84     /** The singleton <code>JDOImplHelper</code> instance.
85      */

86     private static JDOImplHelper jdoImplHelper = new JDOImplHelper();
87     
88     /** The Internationalization message helper.
89      */

90     private final static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
91

92     /** The DateFormat pattern.
93      */

94     private static String JavaDoc dateFormatPattern;
95
96     /** The default DateFormat instance.
97      */

98     private static DateFormat JavaDoc dateFormat;
99
100     /** Register the default DateFormat instance.
101      */

102     static {
103         jdoImplHelper.registerDateFormat(DateFormat.getDateTimeInstance());
104     }
105     
106     /** Creates new JDOImplHelper */
107     private JDOImplHelper() {
108     }
109     
110     /** Get an instance of <code>JDOImplHelper</code>. This method
111      * checks that the caller is authorized for <code>JDOPermission("getMetadata")</code>,
112      * and if not, throws <code>SecurityException</code>.
113      * @return an instance of <code>JDOImplHelper</code>.
114      * @throws SecurityException if the caller is not authorized for JDOPermission("getMetadata").
115      */

116     public static JDOImplHelper getInstance()
117         throws SecurityException JavaDoc {
118         SecurityManager JavaDoc sec = System.getSecurityManager();
119         if (sec != null) {
120             // throws exception if caller is not authorized
121
sec.checkPermission (JDOPermission.GET_METADATA);
122         }
123         return jdoImplHelper;
124     }
125     
126     /** Get the field names for a <code>PersistenceCapable</code> class. The order
127      * of fields is the natural ordering of the <code>String</code> class (without
128      * considering localization).
129      * @param pcClass the <code>PersistenceCapable</code> class.
130      * @return the field names for the class.
131      */

132     public String JavaDoc[] getFieldNames (Class JavaDoc pcClass) {
133         Meta meta = getMeta (pcClass);
134         return meta.getFieldNames();
135     }
136
137     /** Get the field types for a <code>PersistenceCapable</code> class. The order
138      * of fields is the same as for field names.
139      * @param pcClass the <code>PersistenceCapable</code> class.
140      * @return the field types for the class.
141      */

142     public Class JavaDoc[] getFieldTypes (Class JavaDoc pcClass) {
143         Meta meta = getMeta (pcClass);
144         return meta.getFieldTypes();
145     }
146             
147     /** Get the field flags for a <code>PersistenceCapable</code> class. The order
148      * of fields is the same as for field names.
149      * @param pcClass the <code>PersistenceCapable</code> class.
150      * @return the field types for the class.
151      */

152     public byte[] getFieldFlags (Class JavaDoc pcClass) {
153         Meta meta = getMeta (pcClass);
154         return meta.getFieldFlags();
155     }
156             
157     /** Get the persistence-capable superclass for a <code>PersistenceCapable</code> class.
158      * @param pcClass the <code>PersistenceCapable</code> class.
159      * @return The <code>PersistenceCapable</code> superclass for this class,
160      * or <code>null</code> if there isn't one.
161      */

162     public Class JavaDoc getPersistenceCapableSuperclass (Class JavaDoc pcClass) {
163         Meta meta = getMeta (pcClass);
164         return meta.getPersistenceCapableSuperclass();
165     }
166             
167     
168     /** Create a new instance of the class and assign its <code>jdoStateManager</code>.
169      * The new instance has its <code>jdoFlags</code> set to <code>LOAD_REQUIRED</code>.
170      * @see PersistenceCapable#jdoNewInstance(StateManager sm)
171      * @param pcClass the <code>PersistenceCapable</code> class.
172      * @param sm the <code>StateManager</code> which will own the new instance.
173      * @return the new instance, or <code>null</code> if the class is not registered.
174      */

175     public PersistenceCapable newInstance (Class JavaDoc pcClass, StateManager sm) {
176         Meta meta = getMeta (pcClass);
177         PersistenceCapable pcInstance = meta.getPC();
178         return pcInstance == null?null:pcInstance.jdoNewInstance(sm);
179     }
180     
181     /** Create a new instance of the class and assign its <code>jdoStateManager</code> and
182      * key values from the ObjectId. If the oid parameter is <code>null</code>,
183      * no key values are copied.
184      * The new instance has its <code>jdoFlags</code> set to <code>LOAD_REQUIRED</code>.
185      * @see PersistenceCapable#jdoNewInstance(StateManager sm, Object oid)
186      * @param pcClass the <code>PersistenceCapable</code> class.
187      * @param sm the <code>StateManager</code> which will own the new instance.
188      * @return the new instance, or <code>null</code> if the class is not registered.
189      * @param oid the ObjectId instance from which to copy key field values.
190  */

191     public PersistenceCapable newInstance
192             (Class JavaDoc pcClass, StateManager sm, Object JavaDoc oid) {
193         Meta meta = getMeta (pcClass);
194         PersistenceCapable pcInstance = meta.getPC();
195         return pcInstance == null?null:pcInstance.jdoNewInstance(sm, oid);
196     }
197     
198     /** Create a new instance of the ObjectId class of this
199      * <code>PersistenceCapable</code> class.
200      * @param pcClass the <code>PersistenceCapable</code> class.
201      * @return the new ObjectId instance, or <code>null</code> if the class is not registered.
202      */

203     public Object JavaDoc newObjectIdInstance (Class JavaDoc pcClass) {
204         Meta meta = getMeta (pcClass);
205         PersistenceCapable pcInstance = meta.getPC();
206         return pcInstance == null?null:pcInstance.jdoNewObjectIdInstance();
207     }
208     
209     /** Create a new instance of the ObjectId class of this <code>PersistenceCapable</code>
210      * class, using the <code>Object</code> form of the constructor.
211      * @return the new ObjectId instance, or <code>null</code> if the class is not registered.
212      * @param obj the <code>Object</code> form of the object id
213      * @param pcClass the <code>PersistenceCapable</code> class.
214      */

215     public Object JavaDoc newObjectIdInstance (Class JavaDoc pcClass, Object JavaDoc obj) {
216         Meta meta = getMeta (pcClass);
217         PersistenceCapable pcInstance = meta.getPC();
218         return (pcInstance == null)?null:pcInstance.jdoNewObjectIdInstance(obj);
219     }
220     
221     /** Copy fields from an outside source to the key fields in the ObjectId.
222      * This method is generated in the <code>PersistenceCapable</code> class to
223      * generate a call to the field manager for each key field in the ObjectId.
224      * <P>For example, an ObjectId class that has three key fields (<code>int id</code>,
225      * <code>String name</code>, and <code>Float salary</code>) would have the method generated:
226      * <P><code>
227      * void jdoCopyKeyFieldsToObjectId (Object oid, ObjectIdFieldSupplier fm) {
228      * <BR> oid.id = fm.fetchIntField (0);
229      * <BR> oid.name = fm.fetchStringField (1);
230      * <BR> oid.salary = fm.fetchObjectField (2);
231      * <BR>}</code>
232      * <P>The implementation is responsible for implementing the
233      * <code>ObjectIdFieldSupplier</code> to provide the values for the key fields.
234      * @param pcClass the <code>PersistenceCapable Class</code>.
235      * @param oid the ObjectId target of the copy.
236      * @param fm the field manager that supplies the field values.
237  */

238     public void copyKeyFieldsToObjectId
239     (Class JavaDoc pcClass, PersistenceCapable.ObjectIdFieldSupplier fm, Object JavaDoc oid) {
240         Meta meta = getMeta (pcClass);
241         PersistenceCapable pcInstance = meta.getPC();
242         if (pcInstance == null) {
243             throw new JDOFatalInternalException (
244                 msg.msg("ERR_AbstractClassNoIdentity", pcClass.getName())); //NOI18N
245
}
246         pcInstance.jdoCopyKeyFieldsToObjectId(fm, oid);
247     }
248
249     /** Copy fields to an outside source from the key fields in the ObjectId.
250      * This method is generated in the <code>PersistenceCapable</code> class to generate
251      * a call to the field manager for each key field in the ObjectId. For
252      * example, an ObjectId class that has three key fields (<code>int id</code>,
253      * <code>String name</code>, and <code>Float salary</code>) would have the method generated:
254      * <P><code>void jdoCopyKeyFieldsFromObjectId
255      * <BR> (PersistenceCapable oid, ObjectIdFieldConsumer fm) {
256      * <BR> fm.storeIntField (0, oid.id);
257      * <BR> fm.storeStringField (1, oid.name);
258      * <BR> fm.storeObjectField (2, oid.salary);
259      * <BR>}</code>
260      * <P>The implementation is responsible for implementing the
261      * <code>ObjectIdFieldConsumer</code> to store the values for the key fields.
262      * @param pcClass the <code>PersistenceCapable</code> class
263      * @param oid the ObjectId source of the copy.
264      * @param fm the field manager that receives the field values.
265      */

266     public void copyKeyFieldsFromObjectId
267     (Class JavaDoc pcClass, PersistenceCapable.ObjectIdFieldConsumer fm, Object JavaDoc oid) {
268         Meta meta = getMeta (pcClass);
269         PersistenceCapable pcInstance = meta.getPC();
270         if (pcInstance == null) {
271             throw new JDOFatalInternalException (
272                 msg.msg("ERR_AbstractClassNoIdentity", pcClass.getName())); //NOI18N
273
}
274         pcInstance.jdoCopyKeyFieldsFromObjectId(fm, oid);
275     }
276     
277     /** Register metadata by class. The registration will be done in the
278      * class named <code>JDOImplHelper</code> loaded by the same or an
279      * ancestor class loader as the <code>PersistenceCapable</code> class
280      * performing the registration.
281      *
282      * @param pcClass the <code>PersistenceCapable</code> class
283      * used as the key for lookup.
284      * @param fieldNames an array of <code>String</code> field names for persistent and transactional fields
285      * @param fieldTypes an array of <code>Class</code> field types
286      * @param fieldFlags the Field Flags for persistent and transactional fields
287      * @param pc an instance of the <code>PersistenceCapable</code> class
288      * @param persistenceCapableSuperclass the most immediate superclass that is <code>PersistenceCapable</code>
289      */

290     public static void registerClass (Class JavaDoc pcClass,
291             String JavaDoc[] fieldNames, Class JavaDoc[] fieldTypes,
292             byte[] fieldFlags, Class JavaDoc persistenceCapableSuperclass,
293             PersistenceCapable pc) {
294         if (pcClass == null)
295             throw new NullPointerException JavaDoc(msg.msg("ERR_NullClass")); //NOI18N
296
Meta meta = new Meta (fieldNames, fieldTypes,
297             fieldFlags, persistenceCapableSuperclass, pc);
298         registeredClasses.put (pcClass, meta);
299
300         // handle class registration listeners
301
synchronized (listeners) {
302             if (!listeners.isEmpty()) {
303                 RegisterClassEvent event = new RegisterClassEvent(
304                     jdoImplHelper, pcClass, fieldNames, fieldTypes,
305                     fieldFlags, persistenceCapableSuperclass);
306                 for (Iterator JavaDoc i = listeners.iterator(); i.hasNext();) {
307                     RegisterClassListener crl =
308                         (RegisterClassListener)i.next();
309                     if (crl != null) {
310                         crl.registerClass(event);
311                     }
312                 }
313             }
314         }
315     }
316         
317     /**
318      * Unregister metadata by class loader. This method unregisters all
319      * registered <code>PersistenceCapable</code> classes loaded by the
320      * specified class loader. Any attempt to get metadata for unregistered
321      * classes will result in a <code>JDOFatalUserException</code>.
322      * @param cl the class loader.
323      * @since 1.0.2
324      */

325     public void unregisterClasses (ClassLoader JavaDoc cl)
326     {
327         SecurityManager JavaDoc sec = System.getSecurityManager();
328         if (sec != null) {
329             // throws exception if caller is not authorized
330
sec.checkPermission (JDOPermission.MANAGE_METADATA);
331         }
332         synchronized(registeredClasses) {
333             for (Iterator JavaDoc i = registeredClasses.keySet().iterator(); i.hasNext();) {
334                 Class JavaDoc pcClass = (Class JavaDoc)i.next();
335                 // Note, the pc class was registered by calling the static
336
// method JDOImplHelper.registerClass. This means the
337
// JDOImplHelper class loader is the same as or an ancestor
338
// of the class loader of the pc class. In this case method
339
// getClassLoader does not perform a security check for
340
// RuntimePermission("getClassLoader") and thus we do not
341
// need a privileged block for the getClassLoader call.
342
if ((pcClass != null) && (pcClass.getClassLoader() == cl)) {
343                     // unregister pc class, if its class loader is the
344
// specified one.
345
i.remove();
346                 }
347             }
348         }
349     }
350
351     /**
352      * Unregister metadata by class. This method unregisters the specified
353      * class. Any further attempt to get metadata for the specified class will
354      * result in a <code>JDOFatalUserException</code>.
355      * @param pcClass the <code>PersistenceCapable</code> class to be unregistered.
356      * @since 1.0.2
357      */

358     public void unregisterClass (Class JavaDoc pcClass)
359     {
360         if (pcClass == null)
361             throw new NullPointerException JavaDoc(msg.msg("ERR_NullClass")); //NOI18N
362
SecurityManager JavaDoc sec = System.getSecurityManager();
363         if (sec != null) {
364             // throws exception if caller is not authorized
365
sec.checkPermission (JDOPermission.MANAGE_METADATA);
366         }
367         registeredClasses.remove(pcClass);
368     }
369
370     /**
371      * Add the specified <code>RegisterClassListener</code> to the listener list.
372      * @param crl the listener to be added
373      */

374     public void addRegisterClassListener (RegisterClassListener crl) {
375         HashSet JavaDoc alreadyRegisteredClasses = null;
376         synchronized (listeners) {
377             listeners.add(crl);
378             // Make a copy of the existing set of registered classes.
379
// Between these two lines of code, any number of new class registrations
380
// might occur, and will then all wait until this synchronized block completes.
381
// Some of the class registrations might be delivered twice to
382
// the newly registered listener.
383
alreadyRegisteredClasses = new HashSet JavaDoc (registeredClasses.keySet());
384         }
385         // new registrations will call the new listener while the following occurs
386
// notify the new listener about already-registered classes
387
for (Iterator JavaDoc it = alreadyRegisteredClasses.iterator(); it.hasNext();) {
388             Class JavaDoc pcClass = (Class JavaDoc)it.next();
389             Meta meta = getMeta (pcClass);
390             RegisterClassEvent event = new RegisterClassEvent(
391                 this, pcClass, meta.getFieldNames(), meta.getFieldTypes(),
392                 meta.getFieldFlags(), meta.getPersistenceCapableSuperclass());
393             crl.registerClass (event);
394         }
395     }
396
397     /**
398      * Remove the specified <code>RegisterClassListener</code> from the listener list.
399      * @param crl the listener to be removed
400      */

401     public void removeRegisterClassListener (RegisterClassListener crl) {
402         synchronized (listeners) {
403             listeners.remove(crl);
404         }
405     }
406
407     /**
408      * Returns a collection of class objects of the registered
409      * persistence-capable classes.
410      * @return registered persistence-capable classes
411      */

412     public Collection JavaDoc getRegisteredClasses() {
413         return Collections.unmodifiableCollection(registeredClasses.keySet());
414     }
415
416     /** Look up the metadata for a <code>PersistenceCapable</code> class.
417      * @param pcClass the <code>Class</code>.
418      * @return the <code>Meta</code> for the <code>Class</code>.
419      */

420     private static Meta getMeta (Class JavaDoc pcClass) {
421         Meta ret = (Meta) registeredClasses.get (pcClass);
422         if (ret == null) {
423             throw new JDOFatalUserException(
424                 msg.msg ("ERR_NoMetadata", pcClass.getName())); //NOI18N
425
}
426         return ret;
427     }
428     
429     /** Register a class authorized to replaceStateManager. The caller of
430      * this method must be authorized for JDOPermission("setStateManager").
431      * During replaceStateManager, a persistence-capable class will call
432      * the corresponding checkAuthorizedStateManager and the class of the
433      * instance of the parameter must have been registered.
434      * @param smClass a Class that is authorized for JDOPermission("setStateManager").
435      * @throws SecurityException if the caller is not authorized for JDOPermission("setStateManager").
436      * @since 1.0.1
437      */

438     public static void registerAuthorizedStateManagerClass (Class JavaDoc smClass)
439         throws SecurityException JavaDoc {
440         if (smClass == null)
441             throw new NullPointerException JavaDoc(msg.msg("ERR_NullClass")); //NOI18N
442
SecurityManager JavaDoc sm = System.getSecurityManager();
443         if (sm != null) {
444             sm.checkPermission(JDOPermission.SET_STATE_MANAGER);
445         }
446         synchronized (authorizedStateManagerClasses) {
447             authorizedStateManagerClasses.put(smClass, null);
448         }
449     }
450     
451     /** Register classes authorized to replaceStateManager. The caller of
452      * this method must be authorized for JDOPermission("setStateManager").
453      * During replaceStateManager, a persistence-capable class will call
454      * the corresponding checkAuthorizedStateManager and the class of the
455      * instance of the parameter must have been registered.
456      * @param smClasses a Collection of Classes that are authorized for JDOPermission("setStateManager").
457      * @throws SecurityException if the caller is not authorized for JDOPermission("setStateManager").
458      * @since 1.0.1
459      */

460     public static void registerAuthorizedStateManagerClasses (Collection JavaDoc smClasses)
461         throws SecurityException JavaDoc {
462         SecurityManager JavaDoc sm = System.getSecurityManager();
463         if (sm != null) {
464             sm.checkPermission(JDOPermission.SET_STATE_MANAGER);
465             synchronized (authorizedStateManagerClasses) {
466                 for (Iterator JavaDoc it = smClasses.iterator(); it.hasNext();) {
467                     Object JavaDoc smClass = it.next();
468                     if (!(smClass instanceof Class JavaDoc)) {
469                         throw new ClassCastException JavaDoc(
470                             msg.msg("ERR_StateManagerClassCast", //NOI18N
471
smClass.getClass().getName()));
472                     }
473                     registerAuthorizedStateManagerClass((Class JavaDoc)it.next());
474                 }
475             }
476         }
477     }
478     
479     /** Check that the parameter instance is of a class that is authorized for
480      * JDOPermission("setStateManager"). This method is called by the
481      * replaceStateManager method in persistence-capable classes.
482      * A class that is passed as the parameter to replaceStateManager must be
483      * authorized for JDOPermission("setStateManager"). To improve performance,
484      * first the set of authorized classes is checked, and if not present, a
485      * regular permission check is made. The regular permission check requires
486      * that all callers on the stack, including the persistence-capable class
487      * itself, must be authorized for JDOPermission("setStateManager").
488      * @param sm an instance of StateManager whose class is to be checked.
489      * @since 1.0.1
490      */

491     public static void checkAuthorizedStateManager (StateManager sm) {
492         checkAuthorizedStateManagerClass(sm.getClass());
493     }
494
495     /** Check that the parameter instance is a class that is authorized for
496      * JDOPermission("setStateManager"). This method is called by the
497      * constructors of JDO Reference Implementation classes.
498      * @param smClass a Class to be checked for JDOPermission("setStateManager")
499      * @since 1.0.1
500      */

501     public static void checkAuthorizedStateManagerClass (Class JavaDoc smClass) {
502         final SecurityManager JavaDoc scm = System.getSecurityManager();
503         if (scm == null) {
504             // if no security manager, no checking.
505
return;
506         }
507         synchronized(authorizedStateManagerClasses) {
508             if (authorizedStateManagerClasses.containsKey(smClass)) {
509                 return;
510             }
511         }
512         // if not already authorized, perform "long" security checking.
513
scm.checkPermission(JDOPermission.SET_STATE_MANAGER);
514     }
515
516     /**
517      * Construct an instance of a key class using a String as input.
518      * This is a helper interface for use with ObjectIdentity.
519      * Classes without a String constructor (such as those in java.lang
520      * and java.util) will use this interface for constructing new instances.
521      * The result might be a singleton or use some other strategy.
522      */

523     public interface StringConstructor {
524         /**
525          * Construct an instance of the class for which this instance
526          * is registered.
527          * @param s the parameter for construction
528          * @return the constructed object
529          */

530         public Object JavaDoc construct(String JavaDoc s);
531     }
532     
533     /**
534      * Special StringConstructor instances for use with specific
535      * classes that have no public String constructor. The Map is
536      * keyed on class instance and the value is an instance of
537      * StringConstructor.
538      */

539     static Map JavaDoc stringConstructorMap = new HashMap JavaDoc();
540
541     /**
542      *
543      * Register special StringConstructor instances. These instances
544      * are for constructing instances from String parameters where there
545      * is no String constructor for them.
546      * @param cls the class to register a StringConstructor for
547      * @param sc the StringConstructor instance
548      * @return the previous StringConstructor registered for this class
549      */

550     public Object JavaDoc registerStringConstructor(Class JavaDoc cls, StringConstructor sc) {
551         return stringConstructorMap.put(cls, sc);
552     }
553
554     /** Register the default special StringConstructor instances.
555      */

556     static {
557         JDOImplHelper helper = getInstance();
558         if (isClassLoadable("java.util.Currency")) {
559             helper.registerStringConstructor(Currency JavaDoc.class, new StringConstructor() {
560                 public Object JavaDoc construct(String JavaDoc s) {
561                     try {
562                         return Currency.getInstance(s);
563                     } catch (IllegalArgumentException JavaDoc ex) {
564                         throw new javax.jdo.JDOUserException(
565                             msg.msg("EXC_CurrencyStringConstructorIllegalArgument", s), ex); //NOI18N
566
} catch (Exception JavaDoc ex) {
567                         throw new JDOUserException(
568                             msg.msg("EXC_CurrencyStringConstructorException"), ex); //NOI18N
569
}
570                 }
571             });
572         }
573         helper.registerStringConstructor(Locale JavaDoc.class, new StringConstructor() {
574             public Object JavaDoc construct(String JavaDoc s) {
575                 try {
576                     return new Locale JavaDoc(s);
577                 } catch (Exception JavaDoc ex) {
578                     throw new JDOUserException(
579                         msg.msg("EXC_LocaleStringConstructorException"), ex); //NOI18N
580
}
581             }
582         });
583         helper.registerStringConstructor(Date JavaDoc.class, new StringConstructor() {
584             public synchronized Object JavaDoc construct(String JavaDoc s) {
585                 ParsePosition JavaDoc pp = new ParsePosition JavaDoc(0);
586                 Date JavaDoc result = dateFormat.parse(s, pp);
587                 if (result == null) {
588                     throw new JDOUserException (
589                         msg.msg("EXC_DateStringConstructor", new Object JavaDoc[] //NOI18N
590
{s, new Integer JavaDoc(pp.getErrorIndex()), dateFormatPattern}));
591                 }
592                 return result;
593             }
594         });
595     }
596     
597     /**
598      * Determine if a class is loadable in the current environment.
599      */

600     public static boolean isClassLoadable(String JavaDoc className) {
601         try {
602             Class.forName(className);
603             return true;
604         } catch (ClassNotFoundException JavaDoc ex) {
605             return false;
606         }
607     }
608     
609     /**
610      * Construct an instance of the parameter class, using the keyString
611      * as an argument to the constructor. If the class has a StringConstructor
612      * instance registered, use it. If not, try to find a constructor for
613      * the class with a single String argument. Otherwise, throw a
614      * JDOUserException.
615      * @param className the name of the class
616      * @param keyString the String parameter for the constructor
617      * @return the result of construction
618      */

619     public Object JavaDoc construct(String JavaDoc className, String JavaDoc keyString) {
620         synchronized(stringConstructorMap) {
621             try {
622                 Class JavaDoc keyClass = Class.forName(className);
623                 StringConstructor stringConstructor =
624                         (StringConstructor) stringConstructorMap.get(keyClass);
625                 if (stringConstructor == null) {
626                     Constructor JavaDoc keyConstructor =
627                         keyClass.getConstructor(new Class JavaDoc[]{String JavaDoc.class});
628                     return keyConstructor.newInstance(new Object JavaDoc[]{keyString});
629                 } else {
630                     return stringConstructor.construct(keyString);
631                 }
632             } catch (JDOException ex) {
633                 throw ex;
634             } catch (Exception JavaDoc ex) {
635                  /* ClassNotFoundException,
636                     NoSuchMethodException,
637                     InstantiationException,
638                     IllegalAccessException,
639                     InvocationTargetException */

640                 throw new JDOUserException(
641                     msg.msg("EXC_ObjectIdentityStringConstruction", //NOI18N
642
new Object JavaDoc[] {ex.toString(), className, keyString}), ex);
643             }
644         }
645     }
646
647     /**
648      * Register a DateFormat instance for use with constructing Date
649      * instances. The default is the default DateFormat instance.
650      * If the new instance implements SimpleDateFormat, get its pattern
651      * for error messages.
652      * @param df the DateFormat instance to use
653      */

654     public synchronized void registerDateFormat(DateFormat JavaDoc df) {
655         dateFormat = df;
656         if (df instanceof SimpleDateFormat JavaDoc) {
657             dateFormatPattern = ((SimpleDateFormat JavaDoc)df).toPattern();
658         } else {
659             dateFormatPattern = msg.msg("MSG_unknown"); //NOI18N
660
}
661     }
662
663     /** This is a helper class to manage metadata per persistence-capable
664      * class. The information is used at runtime to provide field names and
665      * field types to the JDO Model.
666      *
667      * This is the value of the <code>HashMap</code> which
668      * relates the <code>PersistenceCapable Class</code>
669      * as a key to the metadata.
670      */

671     static class Meta {
672         
673         /** Construct an instance of <code>Meta</code>.
674          * @param fieldNames An array of <code>String</code>
675          * @param fieldTypes An array of <code>Class</code>
676          * @param fieldFlags an array of <code>int</code>
677          * @param persistenceCapableSuperclass the most immediate <code>PersistenceCapable</code> superclass
678          * @param pc An instance of the <code>PersistenceCapable</code> class
679          */

680         Meta (String JavaDoc[] fieldNames, Class JavaDoc[] fieldTypes, byte[] fieldFlags,
681               Class JavaDoc persistenceCapableSuperclass, PersistenceCapable pc) {
682             this.fieldNames = fieldNames;
683             this.fieldTypes = fieldTypes;
684             this.fieldFlags = fieldFlags;
685             this.persistenceCapableSuperclass = persistenceCapableSuperclass;
686             this.pc = pc;
687         }
688     
689         /** This is an array of field names used
690          * for the Model at runtime. The field
691          * is passed by the static class initialization.
692          */

693         String JavaDoc fieldNames[];
694     
695         /** Get the field names from the metadata.
696          * @return the array of field names.
697          */

698         String JavaDoc[] getFieldNames() {
699             return fieldNames;
700         }
701     
702         /** This is an array of field types used
703          * for the Model at runtime. The field
704          * is passed by the static class initialization.
705          */

706         Class JavaDoc fieldTypes[];
707     
708         /** Get the field types from the metadata.
709          * @return the array of field types.
710          */

711         Class JavaDoc[] getFieldTypes() {
712             return fieldTypes;
713         }
714     
715         /** This is an array of field flags used
716          * for the Model at runtime. The field
717          * is passed by the static class initialization.
718          */

719         byte fieldFlags[];
720     
721         /** Get the field types from the metadata.
722          * @return the array of field types.
723          */

724         byte[] getFieldFlags() {
725             return fieldFlags;
726         }
727
728         /** This is the <code>Class</code> instance of the <code>PersistenceCapable</code> superclass.
729          */

730         Class JavaDoc persistenceCapableSuperclass;
731     
732         /** Return the <code>PersistenceCapable</code> superclass.
733          * @return the <code>PersistenceCapable</code> superclass
734          */

735         Class JavaDoc getPersistenceCapableSuperclass() {
736             return persistenceCapableSuperclass;
737         }
738         /** This is an instance of <code>PersistenceCapable</code>,
739          * used at runtime to create new instances.
740          */

741         PersistenceCapable pc;
742     
743         /** Get an instance of the <code>PersistenceCapable</code> class.
744          * @return an instance of the <code>PersistenceCapable Class</code>.
745          */

746         PersistenceCapable getPC() {
747             return pc;
748         }
749     
750         /** Return the string form of the metadata.
751          * @return the string form
752          */

753         public String JavaDoc toString() {
754             return "Meta-" + pc.getClass().getName(); //NOI18N
755
}
756     }
757 }
758
Popular Tags