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