1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package javax.jdo;
23
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileNotFoundException;
27 import java.io.InputStream;
28 import java.io.IOException;
29
30 import java.lang.reflect.Method;
31 import java.lang.reflect.InvocationTargetException;
32
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.Iterator;
36 import java.util.Map;
37 import java.util.Properties;
38
39 import java.security.AccessController;
40 import java.security.PrivilegedAction;
41
42 import javax.jdo.spi.I18NHelper;
43 import javax.jdo.spi.JDOImplHelper;
44 import javax.jdo.spi.JDOImplHelper.StateInterrogationBooleanReturn;
45 import javax.jdo.spi.JDOImplHelper.StateInterrogationObjectReturn;
46 import javax.jdo.spi.PersistenceCapable;
47 import javax.jdo.spi.StateInterrogation;
48 import javax.jdo.spi.StateManager;
49
50 import javax.naming.Context;
51 import javax.naming.InitialContext;
52 import javax.naming.NamingException;
53
54 import javax.rmi.PortableRemoteObject;
55
56
57 /***
58 * This class can be used by a JDO-aware application to call the JDO behavior
59 * of <code>PersistenceCapable</code> instances without declaring them to be
60 * <code>PersistenceCapable</code>.
61 * <P>It is also used to acquire a <code>PersistenceManagerFactory</code> via
62 * various methods.
63 * <P>This helper class defines static methods that allow a JDO-aware
64 * application to examine the runtime state of instances. For example,
65 * an application can discover whether the instance is persistent, transactional,
66 * dirty, new, deleted, or detached; and to get its associated
67 * <code>PersistenceManager</code> if it has one.
68 *
69 * @version 2.0
70 */
71 public class JDOHelper extends Object {
72
73 /*** The Internationalization message helper.
74 */
75 private final static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle");
76
77 /*** The JDOImplHelper instance used for handling non-binary-compatible
78 * implementations.
79 */
80 private static JDOImplHelper implHelper = (JDOImplHelper)
81 AccessController.doPrivileged(
82 new PrivilegedAction () {
83 public Object run () {
84 return JDOImplHelper.getInstance();
85 }
86 }
87 );
88
89 /*** The stateless instance used for handling non-binary-compatible
90 * implementations of getPersistenceManager.
91 */
92 static StateInterrogationObjectReturn getPersistenceManager =
93 new StateInterrogationObjectReturn() {
94 public Object get(Object pc, StateInterrogation si) {
95 return si.getPersistenceManager(pc);
96 }
97 };
98
99 /*** The stateless instance used for handling non-binary-compatible
100 * implementations of getObjectId.
101 */
102 static StateInterrogationObjectReturn getObjectId =
103 new StateInterrogationObjectReturn() {
104 public Object get(Object pc, StateInterrogation si) {
105 return si.getObjectId(pc);
106 }
107 };
108
109 /*** The stateless instance used for handling non-binary-compatible
110 * implementations of getTransactionalObjectId.
111 */
112 static StateInterrogationObjectReturn getTransactionalObjectId =
113 new StateInterrogationObjectReturn() {
114 public Object get(Object pc, StateInterrogation si) {
115 return si.getTransactionalObjectId(pc);
116 }
117 };
118
119 /*** The stateless instance used for handling non-binary-compatible
120 * implementations of getVersion.
121 */
122 static StateInterrogationObjectReturn getVersion =
123 new StateInterrogationObjectReturn() {
124 public Object get(Object pc, StateInterrogation si) {
125 return si.getVersion(pc);
126 }
127 };
128
129 /*** The stateless instance used for handling non-binary-compatible
130 * implementations of isPersistent.
131 */
132 static StateInterrogationBooleanReturn isPersistent =
133 new StateInterrogationBooleanReturn() {
134 public Boolean is(Object pc, StateInterrogation si) {
135 return si.isPersistent(pc);
136 }
137 };
138
139 /*** The stateless instance used for handling non-binary-compatible
140 * implementations of isTransactional.
141 */
142 static StateInterrogationBooleanReturn isTransactional =
143 new StateInterrogationBooleanReturn() {
144 public Boolean is(Object pc, StateInterrogation si) {
145 return si.isTransactional(pc);
146 }
147 };
148
149 /*** The stateless instance used for handling non-binary-compatible
150 * implementations of isDirty.
151 */
152 static StateInterrogationBooleanReturn isDirty =
153 new StateInterrogationBooleanReturn() {
154 public Boolean is(Object pc, StateInterrogation si) {
155 return si.isDirty(pc);
156 }
157 };
158
159 /*** The stateless instance used for handling non-binary-compatible
160 * implementations of isNew.
161 */
162 static StateInterrogationBooleanReturn isNew =
163 new StateInterrogationBooleanReturn() {
164 public Boolean is(Object pc, StateInterrogation si) {
165 return si.isNew(pc);
166 }
167 };
168
169 /*** The stateless instance used for handling non-binary-compatible
170 * implementations of isDeleted.
171 */
172 static StateInterrogationBooleanReturn isDeleted =
173 new StateInterrogationBooleanReturn() {
174 public Boolean is(Object pc, StateInterrogation si) {
175 return si.isDeleted(pc);
176 }
177 };
178
179 /*** The stateless instance used for handling non-binary-compatible
180 * implementations of isDetached.
181 */
182 static StateInterrogationBooleanReturn isDetached =
183 new StateInterrogationBooleanReturn() {
184 public Boolean is(Object pc, StateInterrogation si) {
185 return si.isDetached(pc);
186 }
187 };
188
189 /*** Return the associated <code>PersistenceManager</code> if there is one.
190 * Transactional and persistent instances return the associated
191 * <code>PersistenceManager</code>.
192 *
193 * <P>Transient non-transactional instances and instances of classes
194 * that do not implement <code>PersistenceCapable</code> return <code>null</code>.
195 * @see PersistenceCapable#jdoGetPersistenceManager()
196 * @param pc the <code>PersistenceCapable</code> instance.
197 * @return the <code>PersistenceManager</code> associated with the parameter instance.
198 */
199 public static PersistenceManager getPersistenceManager(Object pc) {
200 if (pc instanceof PersistenceCapable) {
201 return ((PersistenceCapable)pc).jdoGetPersistenceManager();
202 } else {
203 return (PersistenceManager)
204 implHelper.nonBinaryCompatibleGet(pc, getPersistenceManager);
205 }
206 }
207
208 /*** Explicitly mark the parameter instance and field dirty.
209 * Normally, <code>PersistenceCapable</code> classes are able to detect changes made
210 * to their fields. However, if a reference to an array is given to a
211 * method outside the class, and the array is modified, then the
212 * persistent instance is not aware of the change. This API allows the
213 * application to notify the instance that a change was made to a field.
214 *
215 * <P>Transient instances and instances of classes
216 * that do not implement <code>PersistenceCapable</code> ignore this method.
217 * @see PersistenceCapable#jdoMakeDirty(String fieldName)
218 * @param pc the <code>PersistenceCapable</code> instance.
219 * @param fieldName the name of the field to be marked dirty.
220 */
221 public static void makeDirty(Object pc, String fieldName) {
222 if (pc instanceof PersistenceCapable) {
223 ((PersistenceCapable)pc).jdoMakeDirty(fieldName);
224 } else {
225 implHelper.nonBinaryCompatibleMakeDirty(pc, fieldName);
226 }
227 }
228
229 /*** Return a copy of the JDO identity associated with the parameter instance.
230 *
231 * <P>Persistent instances of <code>PersistenceCapable</code> classes have a JDO identity
232 * managed by the <code>PersistenceManager</code>. This method returns a copy of the
233 * ObjectId that represents the JDO identity.
234 *
235 * <P>Transient instances and instances of classes
236 * that do not implement <code>PersistenceCapable</code> return <code>null</code>.
237 *
238 * <P>The ObjectId may be serialized
239 * and later restored, and used with a <code>PersistenceManager</code> from the same JDO
240 * implementation to locate a persistent instance with the same data store
241 * identity.
242 *
243 * <P>If the JDO identity is managed by the application, then the ObjectId may
244 * be used with a <code>PersistenceManager</code> from any JDO implementation that supports
245 * the <code>PersistenceCapable</code> class.
246 *
247 * <P>If the JDO identity is not managed by the application or the data store,
248 * then the ObjectId returned is only valid within the current transaction.
249 *<P>
250 * @see PersistenceManager#getObjectId(Object pc)
251 * @see PersistenceCapable#jdoGetObjectId()
252 * @see PersistenceManager#getObjectById(Object oid, boolean validate)
253 * @param pc the PersistenceCapable instance.
254 * @return a copy of the ObjectId of the parameter instance as of the beginning of the transaction.
255 */
256 public static Object getObjectId(Object pc) {
257 if (pc instanceof PersistenceCapable) {
258 return ((PersistenceCapable)pc).jdoGetObjectId();
259 } else {
260 return implHelper.nonBinaryCompatibleGet(pc, getObjectId);
261 }
262 }
263
264 /*** Get object ids for a collection of instances. For each instance
265 * in the parameter, the getObjectId method is called. This method
266 * returns one identity instance for each element
267 * in the parameter. The order of iteration of the returned
268 * Collection exactly matches the order of iteration of the
269 * parameter Collection.
270 * @param pcs the persistence-capable instances
271 * @return the object ids of the parameters
272 * @see #getObjectId(Object pc)
273 * @see #getObjectIds(Object[] pcs)
274 * @since 2.0
275 */
276 public static Collection getObjectIds(Collection pcs) {
277 ArrayList result = new ArrayList();
278 for (Iterator it = pcs.iterator(); it.hasNext();) {
279 result.add(getObjectId(it.next()));
280 }
281 return result;
282 }
283
284 /*** Get object ids for an array of instances. For each instance
285 * in the parameter, the getObjectId method is called. This method
286 * returns one identity instance for each element
287 * in the parameter. The order of instances of the returned
288 * array exactly matches the order of instances of the
289 * parameter array.
290 * @param pcs the persistence-capable instances
291 * @return the object ids of the parameters
292 * @see #getObjectId(Object pc)
293 * @see #getObjectIds(Collection pcs)
294 * @since 2.0
295 */
296 public static Object[] getObjectIds(Object[] pcs) {
297 Object[] result = new Object[pcs.length];
298 for (int i = 0; i < pcs.length; ++i) {
299 result[i] = getObjectId(pcs[i]);
300 }
301 return result;
302 }
303
304 /*** Return a copy of the JDO identity associated with the parameter instance.
305 *
306 * @see PersistenceCapable#jdoGetTransactionalObjectId()
307 * @see PersistenceManager#getObjectById(Object oid, boolean validate)
308 * @param pc the <code>PersistenceCapable</code> instance.
309 * @return a copy of the ObjectId of the parameter instance as modified in this transaction.
310 */
311 public static Object getTransactionalObjectId(Object pc) {
312 if (pc instanceof PersistenceCapable) {
313 return ((PersistenceCapable)pc).jdoGetTransactionalObjectId();
314 } else {
315 return implHelper.nonBinaryCompatibleGet(pc, getTransactionalObjectId);
316 }
317 }
318
319 /***
320 * Return the version of the instance.
321 * @since 2.0
322 * @param pc the instance
323 * @return the version of the instance
324 */
325 public static Object getVersion (Object pc) {
326 if (pc instanceof PersistenceCapable) {
327 return ((PersistenceCapable)pc).jdoGetVersion();
328 } else {
329 return implHelper.nonBinaryCompatibleGet(pc, getVersion);
330 }
331 }
332 /*** Tests whether the parameter instance is dirty.
333 *
334 * Instances that have been modified, deleted, or newly
335 * made persistent in the current transaction return <code>true</code>.
336 *
337 *<P>Transient instances and instances of classes
338 * that do not implement <code>PersistenceCapable</code> return <code>false</code>.
339 *<P>
340 * @see StateManager#makeDirty(PersistenceCapable pc, String fieldName)
341 * @see PersistenceCapable#jdoIsDirty()
342 * @param pc the <code>PersistenceCapable</code> instance.
343 * @return <code>true</code> if the parameter instance has been modified in the current transaction.
344 */
345 public static boolean isDirty(Object pc) {
346 if (pc instanceof PersistenceCapable) {
347 return ((PersistenceCapable)pc).jdoIsDirty();
348 } else {
349 return implHelper.nonBinaryCompatibleIs(pc, isDirty);
350 }
351 }
352
353 /*** Tests whether the parameter instance is transactional.
354 *
355 * Instances whose state is associated with the current transaction
356 * return true.
357 *
358 *<P>Transient instances and instances of classes
359 * that do not implement <code>PersistenceCapable</code> return <code>false</code>.
360 * @see PersistenceCapable#jdoIsTransactional()
361 * @param pc the <code>PersistenceCapable</code> instance.
362 * @return <code>true</code> if the parameter instance is transactional.
363 */
364 public static boolean isTransactional(Object pc) {
365 if (pc instanceof PersistenceCapable) {
366 return ((PersistenceCapable)pc).jdoIsTransactional();
367 } else {
368 return implHelper.nonBinaryCompatibleIs(pc, isTransactional);
369 }
370 }
371
372 /*** Tests whether the parameter instance is persistent.
373 *
374 * Instances that represent persistent objects in the data store
375 * return <code>true</code>.
376 *
377 *<P>Transient instances and instances of classes
378 * that do not implement <code>PersistenceCapable</code> return <code>false</code>.
379 *<P>
380 * @see PersistenceManager#makePersistent(Object pc)
381 * @see PersistenceCapable#jdoIsPersistent()
382 * @param pc the <code>PersistenceCapable</code> instance.
383 * @return <code>true</code> if the parameter instance is persistent.
384 */
385 public static boolean isPersistent(Object pc) {
386 if (pc instanceof PersistenceCapable) {
387 return ((PersistenceCapable)pc).jdoIsPersistent();
388 } else {
389 return implHelper.nonBinaryCompatibleIs(pc, isPersistent);
390 }
391 }
392
393 /*** Tests whether the parameter instance has been newly made persistent.
394 *
395 * Instances that have been made persistent in the current transaction
396 * return <code>true</code>.
397 *
398 *<P>Transient instances and instances of classes
399 * that do not implement <code>PersistenceCapable</code> return <code>false</code>.
400 *<P>
401 * @see PersistenceManager#makePersistent(Object pc)
402 * @see PersistenceCapable#jdoIsNew()
403 * @param pc the <code>PersistenceCapable</code> instance.
404 * @return <code>true</code> if the parameter instance was made persistent
405 * in the current transaction.
406 */
407 public static boolean isNew(Object pc) {
408 if (pc instanceof PersistenceCapable) {
409 return ((PersistenceCapable)pc).jdoIsNew();
410 } else {
411 return implHelper.nonBinaryCompatibleIs(pc, isNew);
412 }
413 }
414
415 /*** Tests whether the parameter instance has been deleted.
416 *
417 * Instances that have been deleted in the current transaction return <code>true</code>.
418 *
419 *<P>Transient instances and instances of classes
420 * that do not implement <code>PersistenceCapable</code> return <code>false</code>.
421 *<P>
422 * @see PersistenceManager#deletePersistent(Object pc)
423 * @see PersistenceCapable#jdoIsDeleted()
424 * @param pc the <code>PersistenceCapable</code> instance.
425 * @return <code>true</code> if the parameter instance was deleted
426 * in the current transaction.
427 */
428 public static boolean isDeleted(Object pc) {
429 if (pc instanceof PersistenceCapable) {
430 return ((PersistenceCapable)pc).jdoIsDeleted();
431 } else {
432 return implHelper.nonBinaryCompatibleIs(pc, isDeleted);
433 }
434 }
435
436 /***
437 * Tests whether the parameter instance has been detached.
438 *
439 * Instances that have been detached return true.
440 *
441 * <P>Transient instances return false.
442 * <P>
443 * @see PersistenceCapable#jdoIsDetached()
444 * @return <code>true</code> if this instance is detached.
445 * @since 2.0
446 * @param pc the instance
447 */
448 public static boolean isDetached(Object pc) {
449 if (pc instanceof PersistenceCapable) {
450 return ((PersistenceCapable)pc).jdoIsDetached();
451 } else {
452 return implHelper.nonBinaryCompatibleIs(pc, isDetached);
453 }
454 }
455
456 /*** Get a <code>PersistenceManagerFactory</code> based on a <code>Properties</code> instance, using
457 * the current thread's context class loader to locate the
458 * <code>PersistenceManagerFactory</code> class.
459 * @return the <code>PersistenceManagerFactory</code>.
460 * @param props a <code>Properties</code> instance with properties of the <code>PersistenceManagerFactory</code>.
461 * @see #getPersistenceManagerFactory(Map,ClassLoader)
462 */
463 public static PersistenceManagerFactory getPersistenceManagerFactory
464 (Map props) {
465 ClassLoader cl = getContextClassLoader();
466 return getPersistenceManagerFactory (props, cl);
467 }
468
469 /***
470 * Get a <code>PersistenceManagerFactory</code> based on a <code>Properties</code>
471 * instance and a class loader.
472 * The following are standard key values:
473 * <BR><code>"javax.jdo.PersistenceManagerFactoryClass"
474 * <BR>"javax.jdo.option.Optimistic",
475 * <BR>"javax.jdo.option.RetainValues",
476 * <BR>"javax.jdo.option.RestoreValues",
477 * <BR>"javax.jdo.option.IgnoreCache",
478 * <BR>"javax.jdo.option.NontransactionalRead",
479 * <BR>"javax.jdo.option.NontransactionalWrite",
480 * <BR>"javax.jdo.option.Multithreaded",
481 * <BR>"javax.jdo.option.ConnectionUserName",
482 * <BR>"javax.jdo.option.ConnectionPassword",
483 * <BR>"javax.jdo.option.ConnectionURL",
484 * <BR>"javax.jdo.option.ConnectionFactoryName",
485 * <BR>"javax.jdo.option.ConnectionFactory2Name",
486 * <BR>"javax.jdo.option.Mapping",
487 * <BR>"javax.jdo.mapping.Catalog",
488 * <BR>"javax.jdo.mapping.Schema".
489 * </code><P>JDO implementations
490 * are permitted to define key values of their own. Any key values not
491 * recognized by the implementation must be ignored. Key values that are
492 * recognized but not supported by an implementation must result in a
493 * <code>JDOFatalUserException</code> thrown by the method.
494 * <P>The returned <code>PersistenceManagerFactory</code> is not configurable (the
495 * <code>set<I>XXX</I></code> methods will throw an exception).
496 * <P>JDO implementations might manage a map of instantiated
497 * <code>PersistenceManagerFactory</code> instances based on specified property key
498 * values, and return a previously instantiated <code>PersistenceManagerFactory</code>
499 * instance. In this case, the properties of the returned
500 * instance must exactly match the requested properties.
501 * @return the <code>PersistenceManagerFactory</code>.
502 * @param props a <code>Properties</code> instance with properties of the <code>PersistenceManagerFactory</code>.
503 * @param cl the class loader to use to load the <code>PersistenceManagerFactory</code> class
504 */
505 public static PersistenceManagerFactory getPersistenceManagerFactory
506 (Map props, ClassLoader cl) {
507 String pmfClassName = (String) props.get ("javax.jdo.PersistenceManagerFactoryClass");
508 if (pmfClassName == null) {
509 throw new JDOFatalUserException (msg.msg("EXC_GetPMFNoClassNameProperty"));
510 }
511 try {
512 Class pmfClass = cl.loadClass (pmfClassName);
513 Method pmfMethod = pmfClass.getMethod("getPersistenceManagerFactory",
514 new Class[] {Map.class});
515 return (PersistenceManagerFactory) pmfMethod.invoke (null, new Object[] {props});
516 } catch (ClassNotFoundException cnfe) {
517 throw new JDOFatalUserException (msg.msg("EXC_GetPMFClassNotFound", pmfClassName), cnfe);
518 } catch (IllegalAccessException iae) {
519 throw new JDOFatalUserException (msg.msg("EXC_GetPMFIllegalAccess", pmfClassName), iae);
520 } catch (NoSuchMethodException nsme) {
521 throw new JDOFatalInternalException (msg.msg("EXC_GetPMFNoSuchMethod"), nsme);
522 } catch (InvocationTargetException ite) {
523 Throwable nested = ite.getTargetException();
524 if (nested instanceof JDOException) {
525 throw (JDOException)nested;
526 } else throw new JDOFatalInternalException (msg.msg("EXC_GetPMFUnexpectedException"), ite);
527 } catch (NullPointerException e) {
528 throw new JDOFatalInternalException (msg.msg("EXC_GetPMFNullPointerException", pmfClassName), e);
529 } catch (ClassCastException e) {
530 throw new JDOFatalInternalException (msg.msg("EXC_GetPMFClassCastException", pmfClassName), e);
531 } catch (Exception e) {
532 throw new JDOFatalInternalException (msg.msg("EXC_GetPMFUnexpectedException"), e);
533 }
534 }
535
536 /***
537 * Returns a {@link PersistenceManagerFactory} configured based
538 * on the properties stored in the resource at
539 * <code>propsResource</code>. This method is equivalent to
540 * invoking {@link
541 * #getPersistenceManagerFactory(String,ClassLoader)} with
542 * <code>Thread.currentThread().getContextClassLoader()</code> as
543 * the <code>loader</code> argument.
544 * @since 2.0
545 * @param propsResource the resource containing the Properties
546 * @return the PersistenceManagerFactory
547 */
548 public static PersistenceManagerFactory getPersistenceManagerFactory
549 (String propsResource) {
550 return getPersistenceManagerFactory (propsResource,
551 getContextClassLoader());
552 }
553
554 /***
555 * Returns a {@link PersistenceManagerFactory} configured based
556 * on the properties stored in the resource at
557 * <code>propsResource</code>. Loads the resource via
558 * <code>loader</code>, and creates a {@link
559 * PersistenceManagerFactory} with <code>loader</code>. Any
560 * <code>IOException</code>s thrown during resource loading will
561 * be wrapped in a {@link JDOFatalUserException}.
562 * @since 2.0
563 * @param propsResource the resource containing the Properties
564 * @param loader the class loader to use to load both the propsResource and the <code>PersistenceManagerFactory</code> class
565 * @return the PersistenceManagerFactory
566 */
567 public static PersistenceManagerFactory getPersistenceManagerFactory
568 (String propsResource, ClassLoader loader) {
569 return getPersistenceManagerFactory(propsResource, loader, loader);
570 }
571
572 /***
573 * Returns a {@link PersistenceManagerFactory} configured based
574 * on the properties stored in the resource at
575 * <code>propsResource</code>. Loads the Properties via
576 * <code>propsLoader</code>, and creates a {@link
577 * PersistenceManagerFactory} with <code>pmfLoader</code>. Any
578 * <code>IOException</code>s thrown during resource loading will
579 * be wrapped in a {@link JDOFatalUserException}.
580 * @since 2.0
581 * @param propsResource the resource containing the Properties
582 * @param propsLoader the class loader to use to load the propsResource
583 * @param pmfLoader the class loader to use to load the <code>PersistenceManagerFactory</code> class
584 * @return the PersistenceManagerFactory
585 */
586 public static PersistenceManagerFactory getPersistenceManagerFactory
587 (String propsResource, ClassLoader propsLoader, ClassLoader pmfLoader) {
588
589 if (propsResource == null)
590 throw new JDOFatalUserException (msg.msg ("EXC_GetPMFNullResource"));
591 if (propsLoader == null)
592 throw new JDOFatalUserException (msg.msg ("EXC_GetPMFNullPropsLoader"));
593 if (pmfLoader == null)
594 throw new JDOFatalUserException (msg.msg ("EXC_GetPMFNullPMFLoader"));
595
596 Properties props = new Properties ();
597 InputStream in = null;
598 try {
599 in = propsLoader.getResourceAsStream (propsResource);
600 if (in == null)
601 throw new JDOFatalUserException
602 (msg.msg ("EXC_GetPMFNoResource", propsResource, propsLoader));
603 props.load (in);
604 } catch (IOException ioe) {
605 throw new JDOFatalUserException
606 (msg.msg ("EXC_GetPMFIOExceptionRsrc", propsResource), ioe);
607 }
608 finally {
609 if (in != null)
610 try {
611 in.close ();
612 } catch (IOException ioe) { }
613 }
614
615 return getPersistenceManagerFactory (props, pmfLoader);
616 }
617
618
619 /***
620 * Returns a {@link PersistenceManagerFactory} configured based
621 * on the properties stored in the file at
622 * <code>propsFile</code>. This method is equivalent to
623 * invoking {@link
624 * #getPersistenceManagerFactory(File,ClassLoader)} with
625 * <code>Thread.currentThread().getContextClassLoader()</code> as
626 * the <code>loader</code> argument.
627 * @since 2.0
628 * @param propsFile the file containing the Properties
629 * @return the PersistenceManagerFactory
630 */
631 public static PersistenceManagerFactory getPersistenceManagerFactory
632 (File propsFile) {
633 return getPersistenceManagerFactory (propsFile,
634 getContextClassLoader());
635 }
636
637 /***
638 * Returns a {@link PersistenceManagerFactory} configured based
639 * on the properties stored in the file at
640 * <code>propsFile</code>. Creates a {@link
641 * PersistenceManagerFactory} with <code>loader</code>. Any
642 * <code>IOException</code>s or
643 * <code>FileNotFoundException</code>s thrown during resource
644 * loading will be wrapped in a {@link JDOFatalUserException}.
645 * @since 2.0
646 * @param propsFile the file containing the Properties
647 * @param loader the class loader to use to load the <code>PersistenceManagerFactory</code> class
648 * @return the PersistenceManagerFactory
649 */
650 public static PersistenceManagerFactory getPersistenceManagerFactory
651 (File propsFile, ClassLoader loader) {
652 if (propsFile == null)
653 throw new JDOFatalUserException (msg.msg ("EXC_GetPMFNullFile"));
654 if (loader == null)
655 throw new JDOFatalUserException (msg.msg ("EXC_GetPMFNullLoader"));
656 Properties props = new Properties ();
657 InputStream in = null;
658 try {
659 in = new FileInputStream (propsFile);
660 props.load (in);
661 } catch (FileNotFoundException fnfe) {
662 throw new JDOFatalUserException
663 (msg.msg ("EXC_GetPMFNoFile", propsFile, loader), fnfe);
664 } catch (IOException ioe) {
665 throw new JDOFatalUserException
666 (msg.msg ("EXC_GetPMFIOExceptionFile", propsFile), ioe);
667 } finally {
668 if (in != null)
669 try {
670 in.close ();
671 } catch (IOException ioe) { }
672 }
673 return getPersistenceManagerFactory (props, loader);
674 }
675
676 /***
677 * Returns a {@link PersistenceManagerFactory} at the JNDI
678 * location specified by <code>jndiLocation</code> in the context
679 * <code>context</code>. If <code>context</code> is
680 * <code>null</code>, <code>new InitialContext()</code> will be
681 * used. This method is equivalent to invoking {@link
682 * #getPersistenceManagerFactory(String,Context,ClassLoader)}
683 * with <code>Thread.currentThread().getContextClassLoader()</code> as
684 * the <code>loader</code> argument.
685 * @since 2.0
686 * @param jndiLocation the JNDI location containing the PersistenceManagerFactory
687 * @param context the context in which to find the named PersistenceManagerFactory
688 * @return the PersistenceManagerFactory
689 */
690 public static PersistenceManagerFactory getPersistenceManagerFactory
691 (String jndiLocation, Context context) {
692 return getPersistenceManagerFactory (jndiLocation, context,
693 getContextClassLoader());
694 }
695
696
697 /***
698 * Returns a {@link PersistenceManagerFactory} at the JNDI
699 * location specified by <code>jndiLocation</code> in the context
700 * <code>context</code>. If <code>context</code> is
701 * <code>null</code>, <code>new InitialContext()</code> will be
702 * used. Creates a {@link PersistenceManagerFactory} with
703 * <code>loader</code>. Any <code>NamingException</code>s thrown
704 * will be wrapped in a {@link JDOFatalUserException}.
705 * @since 2.0
706 * @param jndiLocation the JNDI location containing the PersistenceManagerFactory
707 * @param context the context in which to find the named PersistenceManagerFactory
708 * @param loader the class loader to use to load the <code>PersistenceManagerFactory</code> class
709 * @return the PersistenceManagerFactory
710 */
711 public static PersistenceManagerFactory getPersistenceManagerFactory
712 (String jndiLocation, Context context, ClassLoader loader) {
713 if (jndiLocation == null)
714 throw new JDOFatalUserException (msg.msg ("EXC_GetPMFNullJndiLoc"));
715 if (loader == null)
716 throw new JDOFatalUserException (msg.msg ("EXC_GetPMFNullLoader"));
717 try {
718 if (context == null)
719 context = new InitialContext ();
720
721 Object o = context.lookup (jndiLocation);
722 return (PersistenceManagerFactory) PortableRemoteObject.narrow
723 (o, PersistenceManagerFactory.class);
724 } catch (NamingException ne) {
725 throw new JDOFatalUserException
726 (msg.msg ("EXC_GetPMFNamingException", jndiLocation, loader), ne);
727 }
728 }
729
730 /***
731 * Returns a {@link PersistenceManagerFactory} configured based
732 * on the Properties stored in the input stream at
733 * <code>stream</code>. This method is equivalent to
734 * invoking {@link
735 * #getPersistenceManagerFactory(InputStream,ClassLoader)} with
736 * <code>Thread.currentThread().getContextClassLoader()</code> as
737 * the <code>loader</code> argument.
738 * @since 2.0
739 * @param stream the stream containing the Properties
740 * @return the PersistenceManagerFactory
741 */
742 public static PersistenceManagerFactory getPersistenceManagerFactory
743 (InputStream stream) {
744 return getPersistenceManagerFactory (stream,
745 getContextClassLoader());
746 }
747
748 /***
749 * Returns a {@link PersistenceManagerFactory} configured based
750 * on the Properties stored in the input stream at
751 * <code>stream</code>. Creates a {@link
752 * PersistenceManagerFactory} with <code>loader</code>. Any
753 * <code>IOException</code>s thrown during resource
754 * loading will be wrapped in a {@link JDOFatalUserException}.
755 * @since 2.0
756 * @param stream the stream containing the Properties
757 * @param loader the class loader to use to load the <code>PersistenceManagerFactory</code> class
758 * @return the PersistenceManagerFactory
759 */
760 public static PersistenceManagerFactory getPersistenceManagerFactory
761 (InputStream stream, ClassLoader loader) {
762 if (stream == null)
763 throw new JDOFatalUserException (msg.msg ("EXC_GetPMFNullStream"));
764 if (loader == null)
765 throw new JDOFatalUserException (msg.msg ("EXC_GetPMFNullLoader"));
766 Properties props = new Properties ();
767 try {
768 props.load (stream);
769 } catch (IOException ioe) {
770 throw new JDOFatalUserException
771 (msg.msg ("EXC_GetPMFIOExceptionStream"), ioe);
772 }
773 return getPersistenceManagerFactory (props, loader);
774 }
775
776 /*** Get the context class loader associated with the current thread.
777 * This is done in a doPrivileged block because it is a secure method.
778 * @return the current thread's context class loader.
779 * @since 2.0
780 */
781 private static ClassLoader getContextClassLoader() {
782 return (ClassLoader)AccessController.doPrivileged(
783 new PrivilegedAction () {
784 public Object run () {
785 return Thread.currentThread().getContextClassLoader();
786 }
787 }
788 );
789 }
790 }