1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package javax.jdo;
24
25 import org.xml.sax.SAXException;
26 import org.xml.sax.SAXParseException;
27 import org.xml.sax.ErrorHandler;
28 import org.w3c.dom.Document;
29 import org.w3c.dom.Element;
30 import org.w3c.dom.NodeList;
31 import org.w3c.dom.Node;
32 import org.w3c.dom.NamedNodeMap;
33
34 import javax.jdo.spi.I18NHelper;
35 import javax.jdo.spi.JDOImplHelper;
36 import javax.jdo.spi.JDOImplHelper.StateInterrogationBooleanReturn;
37 import javax.jdo.spi.JDOImplHelper.StateInterrogationObjectReturn;
38 import javax.jdo.spi.PersistenceCapable;
39 import javax.jdo.spi.StateInterrogation;
40 import javax.naming.Context;
41 import javax.naming.InitialContext;
42 import javax.naming.NamingException;
43 import javax.rmi.PortableRemoteObject;
44 import javax.xml.parsers.DocumentBuilder;
45 import javax.xml.parsers.DocumentBuilderFactory;
46 import javax.xml.parsers.FactoryConfigurationError;
47 import javax.xml.parsers.ParserConfigurationException;
48 import java.lang.reflect.InvocationTargetException;
49 import java.lang.reflect.Method;
50 import java.net.URL;
51 import java.security.AccessController;
52 import java.security.PrivilegedAction;
53 import java.security.PrivilegedActionException;
54 import java.security.PrivilegedExceptionAction;
55 import java.util.Map;
56 import java.util.HashMap;
57 import java.util.Collections;
58 import java.util.Collection;
59 import java.util.Iterator;
60 import java.util.List;
61 import java.util.ArrayList;
62 import java.util.Properties;
63 import java.util.Enumeration;
64 import java.io.IOException;
65 import java.io.InputStream;
66 import java.io.BufferedReader;
67 import java.io.InputStreamReader;
68 import java.io.File;
69 import java.io.FileInputStream;
70 import java.io.FileNotFoundException;
71
72
73 /**
74 * This class can be used by a JDO-aware application to call the JDO behavior
75 * of <code>PersistenceCapable</code> instances without declaring them to be
76 * <code>PersistenceCapable</code>.
77 * <P>It is also used to acquire a <code>PersistenceManagerFactory</code> via
78 * various methods.
79 * <P>This helper class defines static methods that allow a JDO-aware
80 * application to examine the runtime state of instances. For example,
81 * an application can discover whether the instance is persistent,
82 * transactional, dirty, new, deleted, or detached; and to get its associated
83 * <code>PersistenceManager</code> if it has one.
84 *
85 * @version 2.1
86 */
87 public class JDOHelper implements Constants {
88
89 /**
90 * A mapping from jdoconfig.xsd element attributes to PMF properties.
91 */
92 static final Map<String, String> ATTRIBUTE_PROPERTY_XREF
93 = createAttributePropertyXref();
94
95 /** The Internationalization message helper.
96 */
97 private final static I18NHelper msg =
98 I18NHelper.getInstance ("javax.jdo.Bundle");
99
100 /**
101 * Creates a map from jdoconfig.xsd element attributes to PMF properties.
102 * @return An unmodifiable Map of jdoconfig.xsd element attributes to PMF
103 * properties.
104 */
105 static Map<String, String> createAttributePropertyXref() {
106 Map<String, String> xref = new HashMap<String,String>();
107
108 xref.put(
109 PMF_ATTRIBUTE_CLASS,
110 PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS);
111 xref.put(
112 PMF_ATTRIBUTE_CONNECTION_DRIVER_NAME,
113 PROPERTY_CONNECTION_DRIVER_NAME);
114 xref.put(
115 PMF_ATTRIBUTE_CONNECTION_FACTORY_NAME,
116 PROPERTY_CONNECTION_FACTORY_NAME);
117 xref.put(
118 PMF_ATTRIBUTE_CONNECTION_FACTORY2_NAME,
119 PROPERTY_CONNECTION_FACTORY2_NAME);
120 xref.put(
121 PMF_ATTRIBUTE_CONNECTION_PASSWORD,
122 PROPERTY_CONNECTION_PASSWORD);
123 xref.put(
124 PMF_ATTRIBUTE_CONNECTION_URL,
125 PROPERTY_CONNECTION_URL);
126 xref.put(
127 PMF_ATTRIBUTE_CONNECTION_USER_NAME,
128 PROPERTY_CONNECTION_USER_NAME);
129 xref.put(
130 PMF_ATTRIBUTE_IGNORE_CACHE,
131 PROPERTY_IGNORE_CACHE);
132 xref.put(
133 PMF_ATTRIBUTE_MAPPING,
134 PROPERTY_MAPPING);
135 xref.put(
136 PMF_ATTRIBUTE_MULTITHREADED,
137 PROPERTY_MULTITHREADED);
138 xref.put(
139 PMF_ATTRIBUTE_NONTRANSACTIONAL_READ,
140 PROPERTY_NONTRANSACTIONAL_READ);
141 xref.put(
142 PMF_ATTRIBUTE_NONTRANSACTIONAL_WRITE,
143 PROPERTY_NONTRANSACTIONAL_WRITE);
144 xref.put(
145 PMF_ATTRIBUTE_OPTIMISTIC,
146 PROPERTY_OPTIMISTIC);
147 xref.put(
148 PMF_ATTRIBUTE_PERSISTENCE_UNIT_NAME,
149 PROPERTY_PERSISTENCE_UNIT_NAME);
150 xref.put(
151 PMF_ATTRIBUTE_NAME,
152 PROPERTY_NAME);
153 xref.put(
154 PMF_ATTRIBUTE_RESTORE_VALUES,
155 PROPERTY_RESTORE_VALUES);
156 xref.put(
157 PMF_ATTRIBUTE_RETAIN_VALUES,
158 PROPERTY_RETAIN_VALUES);
159 xref.put(
160 PMF_ATTRIBUTE_DETACH_ALL_ON_COMMIT,
161 PROPERTY_DETACH_ALL_ON_COMMIT);
162 xref.put(
163 PMF_ATTRIBUTE_SERVER_TIME_ZONE_ID,
164 PROPERTY_SERVER_TIME_ZONE_ID);
165 xref.put(
166 PMF_ATTRIBUTE_DATASTORE_READ_TIMEOUT_MILLIS,
167 PROPERTY_DATASTORE_READ_TIMEOUT_MILLIS);
168 xref.put(
169 PMF_ATTRIBUTE_DATASTORE_WRITE_TIMEOUT_MILLIS,
170 PROPERTY_DATASTORE_WRITE_TIMEOUT_MILLIS);
171
172 return Collections.unmodifiableMap(xref);
173 }
174
175 /** The JDOImplHelper instance used for handling non-binary-compatible
176 * implementations.
177 */
178 private static JDOImplHelper implHelper = (JDOImplHelper)
179 AccessController.doPrivileged(
180 new PrivilegedAction<JDOImplHelper> () {
181 public JDOImplHelper run () {
182 return JDOImplHelper.getInstance();
183 }
184 }
185 );
186
187 /** The singleton instance of JDOHelper.
188 * @since 2.1
189 */
190 private static JDOHelper instance = new JDOHelper();
191
192 /**
193 * Return the singleton instance of JDOHelper. This instance is
194 * thread-safe.
195 * @since 2.1
196 * @return the thread-safe singleton JDOHelper
197 */
198 public static JDOHelper getInstance() {
199 return instance;
200 }
201
202 /** Some applications might prefer to use instance
203 * methods instead of static methods.
204 * @since 2.1
205 */
206 public JDOHelper() {}
207
208 /** The stateless instance used for handling non-binary-compatible
209 * implementations of getPersistenceManager.
210 */
211 static StateInterrogationObjectReturn getPersistenceManager =
212 new StateInterrogationObjectReturn() {
213 public Object get(Object pc, StateInterrogation si) {
214 return si.getPersistenceManager(pc);
215 }
216 };
217
218 /** The stateless instance used for handling non-binary-compatible
219 * implementations of getObjectId.
220 */
221 static StateInterrogationObjectReturn getObjectId =
222 new StateInterrogationObjectReturn() {
223 public Object get(Object pc, StateInterrogation si) {
224 return si.getObjectId(pc);
225 }
226 };
227
228 /** The stateless instance used for handling non-binary-compatible
229 * implementations of getTransactionalObjectId.
230 */
231 static StateInterrogationObjectReturn getTransactionalObjectId =
232 new StateInterrogationObjectReturn() {
233 public Object get(Object pc, StateInterrogation si) {
234 return si.getTransactionalObjectId(pc);
235 }
236 };
237
238 /** The stateless instance used for handling non-binary-compatible
239 * implementations of getVersion.
240 */
241 static StateInterrogationObjectReturn getVersion =
242 new StateInterrogationObjectReturn() {
243 public Object get(Object pc, StateInterrogation si) {
244 return si.getVersion(pc);
245 }
246 };
247
248 /** The stateless instance used for handling non-binary-compatible
249 * implementations of isPersistent.
250 */
251 static StateInterrogationBooleanReturn isPersistent =
252 new StateInterrogationBooleanReturn() {
253 public Boolean is(Object pc, StateInterrogation si) {
254 return si.isPersistent(pc);
255 }
256 };
257
258 /** The stateless instance used for handling non-binary-compatible
259 * implementations of isTransactional.
260 */
261 static StateInterrogationBooleanReturn isTransactional =
262 new StateInterrogationBooleanReturn() {
263 public Boolean is(Object pc, StateInterrogation si) {
264 return si.isTransactional(pc);
265 }
266 };
267
268 /** The stateless instance used for handling non-binary-compatible
269 * implementations of isDirty.
270 */
271 static StateInterrogationBooleanReturn isDirty =
272 new StateInterrogationBooleanReturn() {
273 public Boolean is(Object pc, StateInterrogation si) {
274 return si.isDirty(pc);
275 }
276 };
277
278 /** The stateless instance used for handling non-binary-compatible
279 * implementations of isNew.
280 */
281 static StateInterrogationBooleanReturn isNew =
282 new StateInterrogationBooleanReturn() {
283 public Boolean is(Object pc, StateInterrogation si) {
284 return si.isNew(pc);
285 }
286 };
287
288 /** The stateless instance used for handling non-binary-compatible
289 * implementations of isDeleted.
290 */
291 static StateInterrogationBooleanReturn isDeleted =
292 new StateInterrogationBooleanReturn() {
293 public Boolean is(Object pc, StateInterrogation si) {
294 return si.isDeleted(pc);
295 }
296 };
297
298 /** The stateless instance used for handling non-binary-compatible
299 * implementations of isDetached.
300 */
301 static StateInterrogationBooleanReturn isDetached =
302 new StateInterrogationBooleanReturn() {
303 public Boolean is(Object pc, StateInterrogation si) {
304 return si.isDetached(pc);
305 }
306 };
307
308 /** Return the associated <code>PersistenceManager</code> if there is one.
309 * Transactional and persistent instances return the associated
310 * <code>PersistenceManager</code>.
311 *
312 * <P>Transient non-transactional instances and instances of classes
313 * that do not implement <code>PersistenceCapable</code> return
314 * <code>null</code>.
315 * @see PersistenceCapable#jdoGetPersistenceManager()
316 * @param pc the <code>PersistenceCapable</code> instance.
317 * @return the <code>PersistenceManager</code> associated with the parameter
318 * instance.
319 */
320 public static PersistenceManager getPersistenceManager(Object pc) {
321 if (pc instanceof PersistenceCapable) {
322 return ((PersistenceCapable)pc).jdoGetPersistenceManager();
323 } else {
324 return (PersistenceManager)
325 implHelper.nonBinaryCompatibleGet(pc, getPersistenceManager);
326 }
327 }
328
329 /** Explicitly mark the parameter instance and field dirty.
330 * Normally, <code>PersistenceCapable</code> classes are able to detect
331 * changes made to their fields. However, if a reference to an array is
332 * given to a method outside the class, and the array is modified, then the
333 * persistent instance is not aware of the change. This API allows the
334 * application to notify the instance that a change was made to a field.
335 *
336 * <P>Transient instances and instances of classes
337 * that do not implement <code>PersistenceCapable</code> ignore this method.
338 * @see PersistenceCapable#jdoMakeDirty(String fieldName)
339 * @param pc the <code>PersistenceCapable</code> instance.
340 * @param fieldName the name of the field to be marked dirty.
341 */
342 public static void makeDirty(Object pc, String fieldName) {
343 if (pc instanceof PersistenceCapable) {
344 ((PersistenceCapable)pc).jdoMakeDirty(fieldName);
345 } else {
346 implHelper.nonBinaryCompatibleMakeDirty(pc, fieldName);
347 }
348 }
349
350 /** Return a copy of the JDO identity associated with the parameter
351 * instance.
352 *
353 * <P>Persistent instances of <code>PersistenceCapable</code> classes have a
354 * JDO identity managed by the <code>PersistenceManager</code>. This method
355 * returns a copy of the ObjectId that represents the JDO identity.
356 *
357 * <P>Transient instances and instances of classes that do not implement
358 * <code>PersistenceCapable</code> return <code>null</code>.
359 *
360 * <P>The ObjectId may be serialized
361 * and later restored, and used with a <code>PersistenceManager</code> from
362 * the same JDO implementation to locate a persistent instance with the same
363 * data store identity.
364 *
365 * <P>If the JDO identity is managed by the application, then the ObjectId
366 * may be used with a <code>PersistenceManager</code> from any JDO
367 * implementation that supports the <code>PersistenceCapable</code> class.
368 *
369 * <P>If the JDO identity is not managed by the application or the data
370 * store, then the ObjectId returned is only valid within the current
371 * transaction.
372 *<P>
373 * @see PersistenceManager#getObjectId(Object pc)
374 * @see PersistenceCapable#jdoGetObjectId()
375 * @see PersistenceManager#getObjectById(Object oid, boolean validate)
376 * @param pc the PersistenceCapable instance.
377 * @return a copy of the ObjectId of the parameter instance as of the
378 * beginning of the transaction.
379 */
380 public static Object getObjectId(Object pc) {
381 if (pc instanceof PersistenceCapable) {
382 return ((PersistenceCapable)pc).jdoGetObjectId();
383 } else {
384 return implHelper.nonBinaryCompatibleGet(pc, getObjectId);
385 }
386 }
387
388 /** Get object ids for a collection of instances. For each instance
389 * in the parameter, the getObjectId method is called. This method
390 * returns one identity instance for each element
391 * in the parameter. The order of iteration of the returned
392 * Collection exactly matches the order of iteration of the
393 * parameter Collection.
394 * @param pcs the persistence-capable instances
395 * @return the object ids of the parameters
396 * @see #getObjectId(Object pc)
397 * @see #getObjectIds(Object[] pcs)
398 * @since 2.0
399 */
400 public static Collection<Object> getObjectIds(Collection<?> pcs) {
401 ArrayList<Object> result = new ArrayList<Object>();
402 for (Iterator<?> it = pcs.iterator(); it.hasNext();) {
403 result.add(getObjectId(it.next()));
404 }
405 return result;
406 }
407
408 /** Get object ids for an array of instances. For each instance
409 * in the parameter, the getObjectId method is called. This method
410 * returns one identity instance for each element
411 * in the parameter. The order of instances of the returned
412 * array exactly matches the order of instances of the
413 * parameter array.
414 * @param pcs the persistence-capable instances
415 * @return the object ids of the parameters
416 * @see #getObjectId(Object pc)
417 * @see #getObjectIds(Collection pcs)
418 * @since 2.0
419 */
420 public static Object[] getObjectIds(Object[] pcs) {
421 Object[] result = new Object[pcs.length];
422 for (int i = 0; i < pcs.length; ++i) {
423 result[i] = getObjectId(pcs[i]);
424 }
425 return result;
426 }
427
428 /** Return a copy of the JDO identity associated with the parameter
429 * instance.
430 *
431 * @see PersistenceCapable#jdoGetTransactionalObjectId()
432 * @see PersistenceManager#getObjectById(Object oid, boolean validate)
433 * @param pc the <code>PersistenceCapable</code> instance.
434 * @return a copy of the ObjectId of the parameter instance as modified in
435 * this transaction.
436 */
437 public static Object getTransactionalObjectId(Object pc) {
438 if (pc instanceof PersistenceCapable) {
439 return ((PersistenceCapable)pc).jdoGetTransactionalObjectId();
440 } else {
441 return implHelper.nonBinaryCompatibleGet(
442 pc, getTransactionalObjectId);
443 }
444 }
445
446 /**
447 * Return the version of the instance.
448 * @since 2.0
449 * @param pc the instance
450 * @return the version of the instance
451 */
452 public static Object getVersion (Object pc) {
453 if (pc instanceof PersistenceCapable) {
454 return ((PersistenceCapable)pc).jdoGetVersion();
455 } else {
456 return implHelper.nonBinaryCompatibleGet(pc, getVersion);
457 }
458 }
459 /** Tests whether the parameter instance is dirty.
460 *
461 * Instances that have been modified, deleted, or newly
462 * made persistent in the current transaction return <code>true</code>.
463 *
464 *<P>Transient instances and instances of classes that do not implement
465 * <code>PersistenceCapable</code> return <code>false</code>.
466 *<P>
467 * @see javax.jdo.spi.StateManager#makeDirty(PersistenceCapable pc,
468 * String fieldName)
469 * @see PersistenceCapable#jdoIsDirty()
470 * @param pc the <code>PersistenceCapable</code> instance.
471 * @return <code>true</code> if the parameter instance has been modified in
472 * the current transaction.
473 */
474 public static boolean isDirty(Object pc) {
475 if (pc instanceof PersistenceCapable) {
476 return ((PersistenceCapable)pc).jdoIsDirty();
477 } else {
478 return implHelper.nonBinaryCompatibleIs(pc, isDirty);
479 }
480 }
481
482 /** Tests whether the parameter instance is transactional.
483 *
484 * Instances whose state is associated with the current transaction
485 * return true.
486 *
487 *<P>Transient instances and instances of classes that do not implement
488 * <code>PersistenceCapable</code> return <code>false</code>.
489 * @see PersistenceCapable#jdoIsTransactional()
490 * @param pc the <code>PersistenceCapable</code> instance.
491 * @return <code>true</code> if the parameter instance is transactional.
492 */
493 public static boolean isTransactional(Object pc) {
494 if (pc instanceof PersistenceCapable) {
495 return ((PersistenceCapable)pc).jdoIsTransactional();
496 } else {
497 return implHelper.nonBinaryCompatibleIs(pc, isTransactional);
498 }
499 }
500
501 /** Tests whether the parameter instance is persistent.
502 *
503 * Instances that represent persistent objects in the data store
504 * return <code>true</code>.
505 *
506 *<P>Transient instances and instances of classes that do not implement
507 * <code>PersistenceCapable</code> return <code>false</code>.
508 *<P>
509 * @see PersistenceManager#makePersistent(Object pc)
510 * @see PersistenceCapable#jdoIsPersistent()
511 * @param pc the <code>PersistenceCapable</code> instance.
512 * @return <code>true</code> if the parameter instance is persistent.
513 */
514 public static boolean isPersistent(Object pc) {
515 if (pc instanceof PersistenceCapable) {
516 return ((PersistenceCapable)pc).jdoIsPersistent();
517 } else {
518 return implHelper.nonBinaryCompatibleIs(pc, isPersistent);
519 }
520 }
521
522 /** Tests whether the parameter instance has been newly made persistent.
523 *
524 * Instances that have been made persistent in the current transaction
525 * return <code>true</code>.
526 *
527 *<P>Transient instances and instances of classes that do not implement
528 * <code>PersistenceCapable</code> return <code>false</code>.
529 *<P>
530 * @see PersistenceManager#makePersistent(Object pc)
531 * @see PersistenceCapable#jdoIsNew()
532 * @param pc the <code>PersistenceCapable</code> instance.
533 * @return <code>true</code> if the parameter instance was made persistent
534 * in the current transaction.
535 */
536 public static boolean isNew(Object pc) {
537 if (pc instanceof PersistenceCapable) {
538 return ((PersistenceCapable)pc).jdoIsNew();
539 } else {
540 return implHelper.nonBinaryCompatibleIs(pc, isNew);
541 }
542 }
543
544 /** Tests whether the parameter instance has been deleted.
545 *
546 * Instances that have been deleted in the current transaction return
547 * <code>true</code>.
548 *
549 *<P>Transient instances and instances of classes that do not implement
550 * <code>PersistenceCapable</code> return <code>false</code>.
551 *<P>
552 * @see PersistenceManager#deletePersistent(Object pc)
553 * @see PersistenceCapable#jdoIsDeleted()
554 * @param pc the <code>PersistenceCapable</code> instance.
555 * @return <code>true</code> if the parameter instance was deleted
556 * in the current transaction.
557 */
558 public static boolean isDeleted(Object pc) {
559 if (pc instanceof PersistenceCapable) {
560 return ((PersistenceCapable)pc).jdoIsDeleted();
561 } else {
562 return implHelper.nonBinaryCompatibleIs(pc, isDeleted);
563 }
564 }
565
566 /**
567 * Tests whether the parameter instance has been detached.
568 *
569 * Instances that have been detached return true.
570 *
571 * <P>Transient instances return false.
572 * <P>
573 * @see PersistenceCapable#jdoIsDetached()
574 * @return <code>true</code> if this instance is detached.
575 * @since 2.0
576 * @param pc the instance
577 */
578 public static boolean isDetached(Object pc) {
579 if (pc instanceof PersistenceCapable) {
580 return ((PersistenceCapable)pc).jdoIsDetached();
581 } else {
582 return implHelper.nonBinaryCompatibleIs(pc, isDetached);
583 }
584 }
585
586 /** Accessor for the state of the passed object.
587 * @param pc The object
588 * @return The object state
589 * @since 2.1
590 */
591 public static ObjectState getObjectState(Object pc) {
592 if (pc == null) {
593 return null;
594 }
595
596 if (isDetached(pc)) {
597 if (isDirty(pc)) {
598
599 return ObjectState.DETACHED_DIRTY;
600 }
601 else {
602
603 return ObjectState.DETACHED_CLEAN;
604 }
605 }
606 else {
607 if (isPersistent(pc)) {
608 if (isTransactional(pc)) {
609 if (isDirty(pc)) {
610 if (isNew(pc)) {
611 if (isDeleted(pc)) {
612
613 return ObjectState.PERSISTENT_NEW_DELETED;
614 } else {
615
616 return ObjectState.PERSISTENT_NEW;
617 }
618 } else {
619 if (isDeleted(pc)) {
620
621 return ObjectState.PERSISTENT_DELETED;
622 } else {
623
624 return ObjectState.PERSISTENT_DIRTY;
625 }
626 }
627 } else {
628
629 return ObjectState.PERSISTENT_CLEAN;
630 }
631 }
632 else {
633 if (isDirty(pc)) {
634
635 return ObjectState.PERSISTENT_NONTRANSACTIONAL_DIRTY;
636 }
637 else {
638
639 return ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL;
640 }
641 }
642 }
643 else {
644 if (isTransactional(pc)) {
645 if (isDirty(pc)) {
646
647 return ObjectState.TRANSIENT_DIRTY;
648 } else {
649
650 return ObjectState.TRANSIENT_CLEAN;
651 }
652 }
653 else {
654
655 return ObjectState.TRANSIENT;
656 }
657 }
658 }
659 }
660
661 /** Get the anonymous <code>PersistenceManagerFactory</code> configured via
662 * the standard configuration file resource "META-INF/jdoconfig.xml", using
663 * the current thread's context class loader
664 * to locate the configuration file resource(s).
665 * @return the anonymous <code>PersistenceManagerFactory</code>.
666 * @since 2.1
667 * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader)
668 */
669 public static PersistenceManagerFactory getPersistenceManagerFactory() {
670 ClassLoader cl = getContextClassLoader();
671 return getPersistenceManagerFactory(
672 null, ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME, cl, cl);
673 }
674
675 /** Get the anonymous <code>PersistenceManagerFactory</code> configured via
676 * the standard configuration file resource "META-INF/jdoconfig.xml", using
677 * the given class loader.
678 * @return the anonymous <code>PersistenceManagerFactory</code>.
679 * @param pmfClassLoader the ClassLoader used to load resources and classes
680 * @since 2.1
681 * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader)
682 */
683 public static PersistenceManagerFactory getPersistenceManagerFactory(
684 ClassLoader pmfClassLoader) {
685 return getPersistenceManagerFactory(
686 null,
687 ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME,
688 pmfClassLoader, pmfClassLoader);
689 }
690
691 /** Get a <code>PersistenceManagerFactory</code> based on a <code>Properties</code>
692 * instance, using the current thread's context class loader to locate the
693 * <code>PersistenceManagerFactory</code> class.
694 * @return the <code>PersistenceManagerFactory</code>.
695 * @param props a <code>Properties</code> instance with properties of the
696 * <code>PersistenceManagerFactory</code>.
697 * @see #getPersistenceManagerFactory(java.util.Map,ClassLoader)
698 */
699 public static PersistenceManagerFactory getPersistenceManagerFactory
700 (Map<?, ?> props) {
701 return getPersistenceManagerFactory(
702 null, props, getContextClassLoader());
703 }
704
705
706 /** Get a <code>PersistenceManagerFactory</code> based on a
707 * <code>Map</code> and a class loader.
708 * This method delegates to the getPersistenceManagerFactory
709 * method that takes a Map of overrides and a Map of properties,
710 * passing null as the overrides parameter.
711 * @see #getPersistenceManagerFactory(java.util.Map, java.util.Map, ClassLoader)
712 * @return the <code>PersistenceManagerFactory</code>.
713 * @param props a <code>Map</code> with properties of the
714 * <code>PersistenceManagerFactory</code>.
715 * @param pmfClassLoader the class loader used to load the
716 * <code>PersistenceManagerFactory</code> class
717 * @since 1.0
718 */
719 public static PersistenceManagerFactory getPersistenceManagerFactory
720 (Map<?, ?> props, ClassLoader pmfClassLoader) {
721 return getPersistenceManagerFactory(
722 null, props, pmfClassLoader);
723 }
724
725 /**
726 * Get a <code>PersistenceManagerFactory</code> based on a
727 * <code>Map</code> of overrides, a <code>Map</code> of
728 * properties, and a class loader.
729 * The following are standard key names:
730 * <BR><code>"javax.jdo.PersistenceManagerFactoryClass"
731 * <BR>"javax.jdo.option.Optimistic",
732 * <BR>"javax.jdo.option.RetainValues",
733 * <BR>"javax.jdo.option.RestoreValues",
734 * <BR>"javax.jdo.option.IgnoreCache",
735 * <BR>"javax.jdo.option.NontransactionalRead",
736 * <BR>"javax.jdo.option.NontransactionalWrite",
737 * <BR>"javax.jdo.option.Multithreaded",
738 * <BR>"javax.jdo.option.ConnectionUserName",
739 * <BR>"javax.jdo.option.ConnectionPassword",
740 * <BR>"javax.jdo.option.ConnectionURL",
741 * <BR>"javax.jdo.option.ConnectionFactoryName",
742 * <BR>"javax.jdo.option.ConnectionFactory2Name",
743 * <BR>"javax.jdo.option.Mapping",
744 * <BR>"javax.jdo.mapping.Catalog",
745 * <BR>"javax.jdo.mapping.Schema",
746 * <BR>"javax.jdo.option.PersistenceUnitName",
747 * <BR>"javax.jdo.option.DetachAllOnCommit",
748 * <BR>"javax.jdo.option.CopyOnAttach",
749 * <BR>"javax.jdo.option.ReadOnly",
750 * <BR>"javax.jdo.option.TransactionIsolationLevel",
751 * <BR>"javax.jdo.option.TransactionType",
752 * <BR>"javax.jdo.option.ServerTimeZoneID",
753 * <BR>"javax.jdo.option.DatastoreReadTimeoutMillis",
754 * <BR>"javax.jdo.option.DatastoreWriteTimeoutMillis",
755 * <BR>"javax.jdo.option.Name".
756 * </code>
757 * and properties of the form
758 * <BR><code>javax.jdo.option.InstanceLifecycleListener.{listenerClass}[=[{pcClasses}]]</code>
759 * where <code>{listenerClass}</code> is the fully qualified name of a
760 * class that implements
761 * {@link javax.jdo.listener.InstanceLifecycleListener}, and
762 * <code>{pcClasses}</code> is an optional comma- or whitespace-delimited
763 * list of persistence-capable classes to be observed; the absence of a
764 * value for a property of this form means that instances of all
765 * persistence-capable classes will be observed by an instance of the given
766 * listener class.
767 * <P>JDO implementations
768 * are permitted to define key values of their own. Any key values not
769 * recognized by the implementation must be ignored. Key values that are
770 * recognized but not supported by an implementation must result in a
771 * <code>JDOFatalUserException</code> thrown by the method.
772 * <P>The returned <code>PersistenceManagerFactory</code> is not
773 * configurable (the <code>set<I>XXX</I></code> methods will throw an
774 * exception).
775 * <P>JDO implementations might manage a map of instantiated
776 * <code>PersistenceManagerFactory</code> instances based on specified
777 * property key values, and return a previously instantiated
778 * <code>PersistenceManagerFactory</code> instance. In this case, the
779 * properties of the returned instance must exactly match the requested
780 * properties.
781 * @return the <code>PersistenceManagerFactory</code>.
782 * @param props a <code>Properties</code> instance with properties of the
783 * <code>PersistenceManagerFactory</code>.
784 * @param pmfClassLoader the class loader to use to load the
785 * <code>PersistenceManagerFactory</code> class
786 * @throws JDOFatalUserException if
787 * <ul><li>the pmfClassLoader passed is invalid; or
788 * </li><li>a valid class name cannot be obtained from
789 * either <code>props</code> or system resources
790 * (an entry in META-INF/services/javax.jdo.PersistenceManagerFactory); or
791 * </li><li>all implementations throw an exception.
792 * </li></ul>
793 * @since 2.1
794 */
795 protected static PersistenceManagerFactory getPersistenceManagerFactory
796 (Map<?, ?> overrides, Map<?, ?> props, ClassLoader pmfClassLoader) {
797 List<Throwable> exceptions = new ArrayList<Throwable>();
798 if (pmfClassLoader == null)
799 throw new JDOFatalUserException (msg.msg (
800 "EXC_GetPMFNullLoader"));
801
802
803 String pmfClassName = (String) props.get (
804 PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS);
805
806 if (!isNullOrBlank(pmfClassName)) {
807
808 return invokeGetPersistenceManagerFactoryOnImplementation(
809 pmfClassName, overrides, props, pmfClassLoader);
810
811 } else {
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828 Enumeration<URL> urls = null;
829 try {
830 urls = getResources(pmfClassLoader,
831 SERVICE_LOOKUP_PMF_RESOURCE_NAME);
832 } catch (Throwable ex) {
833 exceptions.add(ex);
834 }
835
836 if (urls != null){
837 while (urls.hasMoreElements()) {
838
839 try {
840 pmfClassName = getClassNameFromURL(
841 (URL) urls.nextElement());
842
843
844 PersistenceManagerFactory pmf =
845 invokeGetPersistenceManagerFactoryOnImplementation(
846 pmfClassName, overrides, props, pmfClassLoader);
847 return pmf;
848
849 } catch (Throwable ex) {
850
851
852 exceptions.add(ex);
853
854 }
855 }
856 }
857 }
858
859
860
861 throw new JDOFatalUserException(msg.msg(
862 "EXC_GetPMFNoPMFClassNamePropertyOrPUNameProperty"),
863 (Throwable[])
864 exceptions.toArray(new Throwable[exceptions.size()]));
865 }
866
867 /** Get a class name from a URL. The URL is from getResources with
868 * e.g. META-INF/services/javax.jdo.PersistenceManagerFactory as the
869 * parameter. Parse the file, removing blank lines, comment lines,
870 * and comments.
871 * @param url the URL of the services file
872 * @return the name of the class contained in the file
873 * @throws java.io.IOException
874 * @since 2.1
875 */
876
877 protected static String getClassNameFromURL (URL url)
878 throws IOException {
879 InputStream is = openStream(url);
880 BufferedReader reader = new BufferedReader(new InputStreamReader(is));
881 String line = null;
882 try {
883 while ((line = reader.readLine()) != null) {
884 line = line.trim();
885 if (line.length() == 0 || line.startsWith("#")) {
886 continue;
887 }
888
889 String[] tokens = line.split("\\s");
890 String pmfClassName = tokens[0];
891 int indexOfComment = pmfClassName.indexOf("#");
892 if (indexOfComment == -1) {
893 return pmfClassName;
894 }
895
896 return pmfClassName.substring(0, indexOfComment);
897 }
898 return null;
899 } finally {
900 try {
901 reader.close();
902 }
903 catch (IOException x) {
904
905 }
906 }
907 }
908
909 /**
910 * Returns a named {@link PersistenceManagerFactory} or persistence
911 * unit.
912 *
913 * @since 2.1
914 * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader)
915 */
916 public static PersistenceManagerFactory getPersistenceManagerFactory
917 (String name) {
918 ClassLoader cl = getContextClassLoader();
919 return getPersistenceManagerFactory(null, name, cl, cl);
920 }
921
922 /**
923 * Returns a named {@link PersistenceManagerFactory} or persistence
924 * unit.
925 *
926 * @since 1.0
927 * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader)
928 */
929 public static PersistenceManagerFactory getPersistenceManagerFactory
930 (String name, ClassLoader loader) {
931
932 return getPersistenceManagerFactory(null, name, loader, loader);
933 }
934
935 /**
936 * Returns a named {@link PersistenceManagerFactory} or persistence
937 * unit.
938 *
939 * @since 2.0
940 * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader)
941 */
942 public static PersistenceManagerFactory getPersistenceManagerFactory
943 (String name, ClassLoader resourceLoader, ClassLoader pmfLoader) {
944
945 return getPersistenceManagerFactory(
946 null, name, resourceLoader, pmfLoader);
947 }
948
949 /**
950 * Returns a named {@link PersistenceManagerFactory} or persistence
951 * unit.
952 *
953 * @since 2.1
954 * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader)
955 */
956 public static PersistenceManagerFactory getPersistenceManagerFactory
957 (Map<?, ?> overrides, String name) {
958
959 ClassLoader cl = getContextClassLoader();
960 return getPersistenceManagerFactory(overrides, name, cl, cl);
961 }
962
963 /**
964 * Returns a named {@link PersistenceManagerFactory} or persistence
965 * unit.
966 *
967 * @since 2.1
968 * @see #getPersistenceManagerFactory(Map,String,ClassLoader,ClassLoader)
969 */
970 public static PersistenceManagerFactory getPersistenceManagerFactory
971 (Map<?, ?> overrides, String name, ClassLoader resourceLoader) {
972
973 return getPersistenceManagerFactory(
974 overrides, name, resourceLoader, resourceLoader);
975 }
976
977
978 /**
979 * Returns a {@link PersistenceManagerFactory} configured based
980 * on the properties stored in the resource at
981 * <code>name</code>, or, if not found, returns a
982 * {@link PersistenceManagerFactory} with the given
983 * name or, if not found, returns a
984 * <code>javax.persistence.EntityManagerFactory</code> cast to a
985 * {@link PersistenceManagerFactory}. If the name given is null or consists
986 * only of whitespace, it is interpreted as
987 * {@link Constants#ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME}.
988 * The following are standard key names:
989 * <BR><code>"javax.jdo.PersistenceManagerFactoryClass"
990 * <BR>"javax.jdo.option.Optimistic",
991 * <BR>"javax.jdo.option.RetainValues",
992 * <BR>"javax.jdo.option.RestoreValues",
993 * <BR>"javax.jdo.option.IgnoreCache",
994 * <BR>"javax.jdo.option.NontransactionalRead",
995 * <BR>"javax.jdo.option.NontransactionalWrite",
996 * <BR>"javax.jdo.option.Multithreaded",
997 * <BR>"javax.jdo.option.ConnectionUserName",
998 * <BR>"javax.jdo.option.ConnectionPassword",
999 * <BR>"javax.jdo.option.ConnectionURL",
1000 * <BR>"javax.jdo.option.ConnectionFactoryName",
1001 * <BR>"javax.jdo.option.ConnectionFactory2Name",
1002 * <BR>"javax.jdo.option.Mapping",
1003 * <BR>"javax.jdo.mapping.Catalog",
1004 * <BR>"javax.jdo.mapping.Schema",
1005 * <BR>"javax.jdo.option.PersistenceUnitName".
1006 * <BR>"javax.jdo.option.DetachAllOnCommit".
1007 * <BR>"javax.jdo.option.CopyOnAttach".
1008 * <BR>"javax.jdo.option.TransactionType".
1009 * <BR>"javax.jdo.option.ServerTimeZoneID".
1010 * <BR>"javax.jdo.option.DatastoreReadTimeoutMillis",
1011 * <BR>"javax.jdo.option.DatastoreWriteTimeoutMillis",
1012 * <BR>"javax.jdo.option.Name".
1013 * </code>
1014 * and properties of the form
1015 * <BR><code>javax.jdo.option.InstanceLifecycleListener.{listenerClass}[=[{pcClasses}]]</code>
1016 * where <code>{listenerClass}</code> is the fully qualified name of a
1017 * class that implements
1018 * {@link javax.jdo.listener.InstanceLifecycleListener}, and
1019 * <code>{pcClasses}</code> is an optional comma- or whitespace-delimited
1020 * list of persistence-capable classes to be observed; the absence of a
1021 * value for a property of this form means that instances of all
1022 * persistence-capable classes will be observed by an instance of the given
1023 * listener class.
1024 * <P>JDO implementations
1025 * are permitted to define key values of their own. Any key values not
1026 * recognized by the implementation must be ignored. Key values that are
1027 * recognized but not supported by an implementation must result in a
1028 * <code>JDOFatalUserException</code> thrown by the method.
1029 * <P>The returned <code>PersistenceManagerFactory</code> is not
1030 * configurable (the <code>set<I>XXX</I></code> methods will throw an
1031 * exception).
1032 *
1033 * This method loads the properties found at <code>name</code>, if any, via
1034 * <code>resourceLoader</code>, and creates a {@link
1035 * PersistenceManagerFactory} with <code>pmfLoader</code>. Any
1036 * exceptions thrown during resource loading will
1037 * be wrapped in a {@link JDOFatalUserException}.
1038 * If multiple PMFs with the requested name are found, a
1039 * {@link JDOFatalUserException} is thrown.
1040 * @since 2.1
1041 * @param overrides a Map containing properties that override properties
1042 * defined in any resources loaded according to the "name" parameter
1043 * @param name interpreted as the name of the resource containing the PMF
1044 * properties, the name of the PMF, or the persistence unit name, in that
1045 * order; if name is null, blank or whitespace, it is interpreted as
1046 * indicating the anonymous {@link PersistenceManagerFactory}.
1047 * @param resourceLoader the class loader to use to load properties file
1048 * resources; must be non-null if <code>name</code> is non-null or blank
1049 * @param pmfLoader the class loader to use to load the
1050 * {@link PersistenceManagerFactory} or
1051 * <code>javax.persistence.EntityManagerFactory</code> classes
1052 * @return the {@link PersistenceManagerFactory} with properties in the
1053 * given resource, with the given name, or with the given persitence unit
1054 * name
1055 * @see Constants#ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME
1056 */
1057 public static PersistenceManagerFactory getPersistenceManagerFactory(
1058 Map<?, ?> overrides,
1059 String name,
1060 ClassLoader resourceLoader,
1061 ClassLoader pmfLoader) {
1062 if (pmfLoader == null)
1063 throw new JDOFatalUserException (msg.msg (
1064 "EXC_GetPMFNullPMFLoader"));
1065 if (resourceLoader == null) {
1066 throw new JDOFatalUserException(msg.msg(
1067 "EXC_GetPMFNullPropsLoader"));
1068 }
1069
1070 Map<Object,Object> props = null;
1071
1072 name = (name == null?ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME:name.trim());
1073 if (!ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME.equals(name)) {
1074 props = loadPropertiesFromResource(resourceLoader, name);
1075 }
1076
1077 if (props != null) {
1078
1079
1080
1081 props.put(PROPERTY_SPI_RESOURCE_NAME, name);
1082 props.remove(PROPERTY_NAME);
1083 return getPersistenceManagerFactory(overrides, props, pmfLoader);
1084 }
1085
1086 props = getPropertiesFromJdoconfig(name, pmfLoader);
1087 if (props != null) {
1088
1089
1090 props.put(PROPERTY_NAME, name);
1091 props.remove(PROPERTY_SPI_RESOURCE_NAME);
1092
1093 return getPersistenceManagerFactory(overrides, props, pmfLoader);
1094 }
1095
1096 if (!ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME.equals(name)) {
1097 props = new Properties();
1098 props.put(PROPERTY_PERSISTENCE_UNIT_NAME, name);
1099 return getPersistenceManagerFactory(overrides, props, pmfLoader);
1100 }
1101
1102
1103 throw new JDOFatalUserException (msg.msg (
1104 "EXC_NoPMFConfigurableViaPropertiesOrXML", name));
1105 }
1106
1107 /** Invoke the getPersistenceManagerFactory method on the implementation.
1108 * If the overrides parameter to this method is not null, the static method
1109 * with Map overrides, Map properties parameters will be invoked.
1110 * If the overrides parameter to this method is null, the static method
1111 * with Map properties parameter will be invoked.
1112 * @param pmfClassName the name of the implementation factory class
1113 * @param overrides a Map of overrides
1114 * @param properties a Map of properties
1115 * @param cl the class loader to use to load the implementation class
1116 * @return the PersistenceManagerFactory
1117 */
1118 protected static PersistenceManagerFactory
1119 invokeGetPersistenceManagerFactoryOnImplementation(
1120 String pmfClassName, Map<?, ?> overrides, Map<?, ?> properties, ClassLoader cl) {
1121 if (overrides != null) {
1122
1123 try {
1124 Class<?> implClass = forName(pmfClassName, true, cl);
1125 Method m = getMethod(implClass,
1126 "getPersistenceManagerFactory",
1127 new Class[]{Map.class, Map.class});
1128 PersistenceManagerFactory pmf =
1129 (PersistenceManagerFactory) invoke(m,
1130 null, new Object[]{overrides, properties});
1131 if (pmf == null) {
1132 throw new JDOFatalInternalException(msg.msg (
1133 "EXC_GetPMFNullPMF", pmfClassName));
1134 }
1135 return pmf;
1136
1137 } catch (ClassNotFoundException e) {
1138 throw new JDOFatalUserException(msg.msg(
1139 "EXC_GetPMFClassNotFound", pmfClassName), e);
1140 } catch (NoSuchMethodException e) {
1141 throw new JDOFatalInternalException(msg.msg(
1142 "EXC_GetPMFNoSuchMethod2", pmfClassName), e);
1143 } catch (NullPointerException e) {
1144 throw new JDOFatalInternalException (msg.msg(
1145 "EXC_GetPMFNullPointerException", pmfClassName), e);
1146 } catch (IllegalAccessException e) {
1147 throw new JDOFatalUserException(msg.msg(
1148 "EXC_GetPMFIllegalAccess", pmfClassName), e);
1149 } catch (ClassCastException e) {
1150 throw new JDOFatalInternalException (msg.msg(
1151 "EXC_GetPMFClassCastException", pmfClassName), e);
1152 } catch (InvocationTargetException ite) {
1153 Throwable nested = ite.getTargetException();
1154 if (nested instanceof JDOException) {
1155 throw (JDOException)nested;
1156 } else throw new JDOFatalInternalException (msg.msg(
1157 "EXC_GetPMFUnexpectedException"), ite);
1158 }
1159 } else {
1160
1161 try {
1162 Class<?> implClass = forName(pmfClassName, true, cl);
1163 Method m = getMethod(implClass,
1164 "getPersistenceManagerFactory",
1165 new Class[]{Map.class});
1166 PersistenceManagerFactory pmf =
1167 (PersistenceManagerFactory) invoke(m,
1168 null, new Object[]{properties});
1169 if (pmf == null) {
1170 throw new JDOFatalInternalException(msg.msg (
1171 "EXC_GetPMFNullPMF", pmfClassName));
1172 }
1173 return pmf;
1174 } catch (ClassNotFoundException e) {
1175 throw new JDOFatalUserException(msg.msg(
1176 "EXC_GetPMFClassNotFound", pmfClassName), e);
1177 } catch (NoSuchMethodException e) {
1178 throw new JDOFatalInternalException(msg.msg(
1179 "EXC_GetPMFNoSuchMethod", pmfClassName), e);
1180 } catch (NullPointerException e) {
1181 throw new JDOFatalInternalException (msg.msg(
1182 "EXC_GetPMFNullPointerException", pmfClassName), e);
1183 } catch (IllegalAccessException e) {
1184 throw new JDOFatalUserException(msg.msg(
1185 "EXC_GetPMFIllegalAccess", pmfClassName), e);
1186 } catch (ClassCastException e) {
1187 throw new JDOFatalInternalException (msg.msg(
1188 "EXC_GetPMFClassCastException", pmfClassName), e);
1189 } catch (InvocationTargetException ite) {
1190 Throwable nested = ite.getTargetException();
1191 if (nested instanceof JDOException) {
1192 throw (JDOException)nested;
1193 } else throw new JDOFatalInternalException (msg.msg(
1194 "EXC_GetPMFUnexpectedException"), ite);
1195 }
1196 }
1197 }
1198
1199 /** Load a Properties instance by name from the class loader.
1200 *
1201 * @param resourceLoader the class loader from which to load the properties
1202 * @param name the name of the resource
1203 * @return a Properties instance or null if no resource is found
1204 */
1205 protected static Map<Object,Object> loadPropertiesFromResource(
1206 ClassLoader resourceLoader, String name) {
1207 InputStream in = null;
1208 Properties props = null;
1209
1210 try {
1211 in = getResourceAsStream(resourceLoader, name);
1212 if (in != null) {
1213
1214
1215 props = new Properties();
1216 ((Properties) props).load(in);
1217 }
1218 } catch (IOException ioe) {
1219 throw new JDOFatalUserException(msg.msg(
1220 "EXC_GetPMFIOExceptionRsrc", name), ioe);
1221 } finally {
1222 if (in != null) {
1223 try {
1224 in.close();
1225 } catch (IOException ioe) {
1226 }
1227 }
1228 }
1229 return props;
1230 }
1231
1232 /**
1233 * @see #getNamedPMFProperties(String,ClassLoader,String)
1234 * @since 2.1
1235 */
1236 protected static Map<Object,Object> getPropertiesFromJdoconfig(
1237 String name,
1238 ClassLoader resourceLoader) {
1239 return getNamedPMFProperties(
1240 name, resourceLoader, JDOCONFIG_RESOURCE_NAME);
1241 }
1242
1243 /**
1244 * Find and return the named {@link PersistenceManagerFactory}'s properties,
1245 * or null if not found.
1246 * If multiple named PMF property sets with
1247 * the given name are found (including anonymous ones), throw
1248 * {@link JDOFatalUserException}.
1249 * This method is here only to facilitate testing; the parameter
1250 * "jdoconfigResourceName" in public usage should always have the value
1251 * given in the constant {@link Constants#JDOCONFIG_RESOURCE_NAME}.
1252 *
1253 * @param name The persistence unit name; null is disallowed.
1254 * @param resourceLoader The ClassLoader used to load the standard JDO
1255 * configuration file.
1256 * @param jdoconfigResourceName The name of the configuration file to read.
1257 * In public usage, this should always be the value of
1258 * {@link Constants#JDOCONFIG_RESOURCE_NAME}.
1259 * @return The named <code>PersistenceManagerFactory</code> properties if
1260 * found, null if not.
1261 * @since 2.1
1262 * @throws JDOFatalUserException if multiple named PMF property sets are
1263 * found with the given name, or any other exception is encountered.
1264 */
1265 protected static Map<Object,Object> getNamedPMFProperties(
1266 String name,
1267 ClassLoader resourceLoader,
1268 String jdoconfigResourceName) {
1269
1270 Map<String,Map<Object,Object>> propertiesByNameInAllConfigs
1271 = new HashMap<String,Map<Object,Object>>();
1272 try {
1273 URL firstFoundConfigURL = null;
1274
1275
1276 Enumeration<URL> resources =
1277 getResources(resourceLoader, jdoconfigResourceName);
1278
1279 if (resources.hasMoreElements()) {
1280 ArrayList<URL> processedResources = new ArrayList<URL>();
1281
1282
1283 DocumentBuilderFactory factory = getDocumentBuilderFactory();
1284 do {
1285 URL currentConfigURL = resources.nextElement();
1286 if (processedResources.contains(currentConfigURL)) {
1287 continue;
1288 }
1289 else {
1290 processedResources.add(currentConfigURL);
1291 }
1292
1293 Map<String,Map<Object,Object>> propertiesByNameInCurrentConfig =
1294 readNamedPMFProperties(
1295 currentConfigURL,
1296 name,
1297 factory);
1298
1299
1300 if (propertiesByNameInCurrentConfig.containsKey(name)) {
1301
1302 if (firstFoundConfigURL == null) {
1303 firstFoundConfigURL = currentConfigURL;
1304 }
1305
1306 if (propertiesByNameInAllConfigs.containsKey(name))
1307 throw new JDOFatalUserException (msg.msg(
1308 "EXC_DuplicateRequestedNamedPMFFoundInDifferentConfigs",
1309 "".equals(name)
1310 ? "(anonymous)"
1311 : name,
1312 firstFoundConfigURL.toExternalForm(),
1313 currentConfigURL.toExternalForm()));
1314 }
1315
1316 propertiesByNameInAllConfigs
1317 .putAll(propertiesByNameInCurrentConfig);
1318 } while (resources.hasMoreElements());
1319 }
1320 }
1321 catch (FactoryConfigurationError e) {
1322 throw new JDOFatalUserException(
1323 msg.msg("ERR_NoDocumentBuilderFactory"), e);
1324 }
1325 catch (IOException ioe) {
1326 throw new JDOFatalUserException (msg.msg (
1327 "EXC_GetPMFIOExceptionRsrc", name), ioe);
1328 }
1329
1330
1331
1332 return (Map<Object,Object>) propertiesByNameInAllConfigs.get(name);
1333 }
1334
1335
1336 protected static DocumentBuilderFactory getDocumentBuilderFactory() {
1337 @SuppressWarnings("static-access")
1338 DocumentBuilderFactory factory =
1339 implHelper.getRegisteredDocumentBuilderFactory();
1340 if (factory == null) {
1341 factory = getDefaultDocumentBuilderFactory();
1342 }
1343 return factory;
1344 }
1345
1346 protected static DocumentBuilderFactory getDefaultDocumentBuilderFactory() {
1347 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
1348 factory.setIgnoringComments(true);
1349 factory.setNamespaceAware(true);
1350 factory.setValidating(false);
1351 factory.setIgnoringElementContentWhitespace(true);
1352 factory.setExpandEntityReferences(true);
1353
1354 return factory;
1355 }
1356
1357 protected static ErrorHandler getErrorHandler() {
1358 @SuppressWarnings("static-access")
1359 ErrorHandler handler = implHelper.getRegisteredErrorHandler();
1360 if (handler == null) {
1361 handler = getDefaultErrorHandler();
1362 }
1363 return handler;
1364 }
1365
1366 protected static ErrorHandler getDefaultErrorHandler() {
1367 return new ErrorHandler() {
1368 public void error(SAXParseException exception)
1369 throws SAXException {
1370 throw exception;
1371 }
1372
1373 public void fatalError(SAXParseException exception)
1374 throws SAXException {
1375 throw exception;
1376 }
1377
1378 public void warning(SAXParseException exception)
1379 throws SAXException {
1380
1381 }
1382 };
1383 }
1384
1385
1386 /** Reads JDO configuration file, creates a Map for each
1387 * persistence-manager-factory, then returns the map.
1388 * @param url URL of a JDO configuration file compliant with
1389 * javax/jdo/jdoconfig.xsd.
1390 * @param requestedPMFName The name of the requested
1391 * persistence unit (allows for fail-fast).
1392 * @param factory The <code>DocumentBuilderFactory</code> to use for XML
1393 * parsing.
1394 * @return a Map<String,Map> holding persistence unit configurations; for
1395 * the anonymous persistence unit, the
1396 * value of the String key is the empty string, "".
1397 */
1398 protected static Map<String,Map<Object,Object>> readNamedPMFProperties(
1399 URL url,
1400 String requestedPMFName,
1401 DocumentBuilderFactory factory) {
1402 requestedPMFName = requestedPMFName == null
1403 ? ""
1404 : requestedPMFName.trim();
1405
1406 Map<String,Map<Object,Object>>
1407 propertiesByName = new HashMap<String,Map<Object,Object>>();
1408 InputStream in = null;
1409 try {
1410 DocumentBuilder builder = factory.newDocumentBuilder();
1411 builder.setErrorHandler(getErrorHandler());
1412
1413 in = openStream(url);
1414 Document doc = builder.parse(in);
1415
1416 Element root = doc.getDocumentElement();
1417 if (root == null) {
1418 throw new JDOFatalUserException(
1419 msg.msg("EXC_InvalidJDOConfigNoRoot", url.toExternalForm())
1420 );
1421 }
1422
1423 NodeList pmfs = root.getElementsByTagName(
1424 ELEMENT_PERSISTENCE_MANAGER_FACTORY);
1425
1426 for(int i = 0; i < pmfs.getLength(); i++) {
1427 Node pmfElement = pmfs.item(i);
1428
1429 Properties pmfPropertiesFromAttributes
1430 = readPropertiesFromPMFElementAttributes(pmfElement);
1431
1432 Properties pmfPropertiesFromElements
1433 = readPropertiesFromPMFSubelements(pmfElement, url);
1434
1435
1436 String pmfNameFromAtts =
1437 pmfPropertiesFromAttributes.getProperty(PROPERTY_NAME);
1438 String pmfNameFromElem =
1439 pmfPropertiesFromElements.getProperty(PROPERTY_NAME);
1440
1441 String pmfName = null;
1442 if (isNullOrBlank(pmfNameFromAtts)) {
1443
1444 if (!isNullOrBlank(pmfNameFromElem)) {
1445
1446 pmfName = pmfNameFromElem;
1447 }
1448 else {
1449
1450 pmfName = ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME;
1451 }
1452 }
1453 else {
1454
1455 if (!isNullOrBlank(pmfNameFromElem)) {
1456
1457 throw new JDOFatalUserException(
1458 msg.msg(
1459 "EXC_DuplicatePMFNamePropertyFoundWithinConfig",
1460 pmfNameFromAtts,
1461 pmfNameFromElem,
1462 url.toExternalForm()));
1463 }
1464 pmfName = pmfNameFromAtts;
1465 }
1466 pmfName = pmfName == null ? "" : pmfName.trim();
1467
1468
1469 if (requestedPMFName.equals(pmfName)) {
1470 Iterator<?> it =
1471 pmfPropertiesFromAttributes.keySet().iterator();
1472 while (it.hasNext()) {
1473 String property = (String) it.next();
1474 if (pmfPropertiesFromElements.contains(property)) {
1475 throw new JDOFatalUserException(
1476 msg.msg(
1477 "EXC_DuplicatePropertyFound",
1478 property,
1479 pmfName,
1480 url.toExternalForm()));
1481 }
1482 }
1483 }
1484
1485
1486
1487 Properties pmfProps = new Properties();
1488 pmfProps.putAll(pmfPropertiesFromAttributes);
1489 pmfProps.putAll(pmfPropertiesFromElements);
1490
1491
1492 if (pmfName.equals(requestedPMFName)
1493 && propertiesByName.containsKey(pmfName)) {
1494
1495 throw new JDOFatalUserException(msg.msg(
1496 "EXC_DuplicateRequestedNamedPMFFoundInSameConfig",
1497 pmfName,
1498 url.toExternalForm()));
1499 }
1500 propertiesByName.put(pmfName, pmfProps);
1501 }
1502 return propertiesByName;
1503 }
1504 catch (IOException ioe) {
1505 throw new JDOFatalUserException(
1506 msg.msg("EXC_GetPMFIOExceptionRsrc", url.toString()),
1507 ioe);
1508 }
1509 catch (ParserConfigurationException e) {
1510 throw new JDOFatalInternalException(
1511 msg.msg("EXC_ParserConfigException"),
1512 e);
1513 }
1514 catch (SAXParseException e) {
1515 throw new JDOFatalUserException(
1516 msg.msg(
1517 "EXC_SAXParseException",
1518 url.toExternalForm(),
1519 new Integer(e.getLineNumber()),
1520 new Integer(e.getColumnNumber())),
1521 e);
1522 }
1523 catch (SAXException e) {
1524 throw new JDOFatalUserException(
1525 msg.msg("EXC_SAXException", url.toExternalForm()),
1526 e);
1527 }
1528 catch (JDOException e) {
1529 throw e;
1530 }
1531 catch (RuntimeException e) {
1532 throw new JDOFatalUserException(
1533 msg.msg("EXC_SAXException", url.toExternalForm()),
1534 e);
1535 }
1536 finally {
1537 if (in != null) {
1538 try {
1539 in.close();
1540 }
1541 catch (IOException ioe) {
1542 }
1543 }
1544 }
1545
1546 protected static Properties readPropertiesFromPMFElementAttributes(
1547 Node pmfElement) {
1548 Properties p = new Properties();
1549 NamedNodeMap attributes = pmfElement.getAttributes();
1550 if (attributes == null) {
1551 return p;
1552 }
1553
1554 for(int i = 0; i < attributes.getLength(); i++) {
1555 Node att = attributes.item(i);
1556 String attName = att.getNodeName();
1557 String attValue = att.getNodeValue().trim();
1558
1559 String jdoPropertyName =
1560 (String) ATTRIBUTE_PROPERTY_XREF.get(attName);
1561
1562 p.put(
1563 jdoPropertyName != null
1564 ? jdoPropertyName
1565 : attName,
1566 attValue);
1567 }
1568
1569 return p;
1570 }
1571
1572 protected static Properties readPropertiesFromPMFSubelements(
1573 Node pmfElement, URL url) {
1574 Properties p = new Properties();
1575 NodeList elements = pmfElement.getChildNodes();
1576 if (elements == null) {
1577 return p;
1578 }
1579 for(int i = 0; i < elements.getLength(); i++) {
1580 Node element = elements.item(i);
1581 if (element.getNodeType() != Node.ELEMENT_NODE) {
1582 continue;
1583 }
1584
1585 String elementName = element.getNodeName();
1586 NamedNodeMap attributes = element.getAttributes();
1587 if (ELEMENT_PROPERTY.equalsIgnoreCase(elementName)) {
1588
1589
1590
1591 Node nameAtt = attributes.getNamedItem(PROPERTY_ATTRIBUTE_NAME);
1592 if (nameAtt == null) {
1593 throw new JDOFatalUserException(
1594 msg.msg("EXC_PropertyElementHasNoNameAttribute", url));
1595 }
1596 String name = nameAtt.getNodeValue().trim();
1597 if ("".equals(name)) {
1598 throw new JDOFatalUserException(
1599 msg.msg(
1600 "EXC_PropertyElementNameAttributeHasNoValue",
1601 name,
1602 url));
1603 }
1604
1605
1606
1607
1608 String jdoPropertyName =
1609 (String) ATTRIBUTE_PROPERTY_XREF.get(name);
1610
1611 String propertyName = jdoPropertyName != null
1612 ? jdoPropertyName
1613 : name;
1614
1615 if (p.containsKey(propertyName)) {
1616 throw new JDOFatalUserException(
1617 msg.msg(
1618 "EXC_DuplicatePropertyNameGivenInPropertyElement",
1619 propertyName,
1620 url));
1621 }
1622
1623
1624 Node valueAtt = attributes.getNamedItem(
1625 PROPERTY_ATTRIBUTE_VALUE);
1626 String value = valueAtt == null
1627 ? null
1628 : valueAtt.getNodeValue().trim();
1629
1630 p.put(propertyName, value);
1631 }
1632 else if (ELEMENT_INSTANCE_LIFECYCLE_LISTENER.equals(elementName)) {
1633
1634
1635
1636 Node listenerAtt = attributes.getNamedItem(
1637 INSTANCE_LIFECYCLE_LISTENER_ATTRIBUTE_LISTENER);
1638 if (listenerAtt == null) {
1639 throw new JDOFatalUserException(
1640 msg.msg(
1641 "EXC_MissingListenerAttribute",
1642 url));
1643 }
1644 String listener = listenerAtt.getNodeValue().trim();
1645 if ("".equals(listener)) {
1646 throw new JDOFatalUserException(
1647 msg.msg(
1648 "EXC_MissingListenerAttributeValue",
1649 url));
1650 }
1651
1652
1653
1654 listener =
1655 PROPERTY_PREFIX_INSTANCE_LIFECYCLE_LISTENER + listener;
1656
1657
1658 Node classesAtt = attributes.getNamedItem(
1659 INSTANCE_LIFECYCLE_LISTENER_ATTRIBUTE_CLASSES);
1660 String value = classesAtt == null
1661 ? ""
1662 : classesAtt.getNodeValue().trim();
1663
1664 p.put(listener, value);
1665 }
1666 }
1667 return p;
1668 }
1669
1670 protected static boolean isNullOrBlank(String s) {
1671 return s == null || "".equals(s.trim());
1672 }
1673
1674 /**
1675 * Returns a {@link PersistenceManagerFactory} configured based
1676 * on the properties stored in the file at
1677 * <code>propsFile</code>. This method is equivalent to
1678 * invoking {@link
1679 * #getPersistenceManagerFactory(File,ClassLoader)} with
1680 * <code>Thread.currentThread().getContextClassLoader()</code> as
1681 * the <code>loader</code> argument.
1682 * @since 2.0
1683 * @param propsFile the file containing the Properties
1684 * @return the PersistenceManagerFactory
1685 */
1686 public static PersistenceManagerFactory getPersistenceManagerFactory
1687 (File propsFile) {
1688 return getPersistenceManagerFactory(
1689 propsFile, getContextClassLoader());
1690 }
1691
1692 /**
1693 * Returns a {@link PersistenceManagerFactory} configured based
1694 * on the properties stored in the file at
1695 * <code>propsFile</code>. Creates a {@link
1696 * PersistenceManagerFactory} with <code>loader</code>. Any
1697 * <code>IOException</code>s or
1698 * <code>FileNotFoundException</code>s thrown during resource
1699 * loading will be wrapped in a {@link JDOFatalUserException}.
1700 * @since 2.0
1701 * @param propsFile the file containing the Properties
1702 * @param loader the class loader to use to load the
1703 * <code>PersistenceManagerFactory</code> class
1704 * @return the PersistenceManagerFactory
1705 */
1706 public static PersistenceManagerFactory getPersistenceManagerFactory
1707 (File propsFile, ClassLoader loader) {
1708 if (propsFile == null)
1709 throw new JDOFatalUserException (msg.msg (
1710 "EXC_GetPMFNullFile"));
1711
1712 InputStream in = null;
1713 try {
1714 in = new FileInputStream(propsFile);
1715 return getPersistenceManagerFactory(in, loader);
1716 } catch (FileNotFoundException fnfe) {
1717 throw new JDOFatalUserException (msg.msg (
1718 "EXC_GetPMFNoFile", propsFile), fnfe);
1719 } finally {
1720 if (in != null)
1721 try {
1722 in.close ();
1723 } catch (IOException ioe) { }
1724 }
1725 }
1726
1727 /**
1728 * Returns a {@link PersistenceManagerFactory} at the JNDI
1729 * location specified by <code>jndiLocation</code> in the context
1730 * <code>context</code>. If <code>context</code> is
1731 * <code>null</code>, <code>new InitialContext()</code> will be
1732 * used. This method is equivalent to invoking {@link
1733 * #getPersistenceManagerFactory(String,Context,ClassLoader)}
1734 * with <code>Thread.currentThread().getContextClassLoader()</code> as
1735 * the <code>loader</code> argument.
1736 * @since 2.0
1737 * @param jndiLocation the JNDI location containing the
1738 * PersistenceManagerFactory
1739 * @param context the context in which to find the named
1740 * PersistenceManagerFactory
1741 * @return the PersistenceManagerFactory
1742 */
1743 public static PersistenceManagerFactory getPersistenceManagerFactory
1744 (String jndiLocation, Context context) {
1745 return getPersistenceManagerFactory (jndiLocation, context,
1746 getContextClassLoader());
1747 }
1748
1749
1750 /**
1751 * Returns a {@link PersistenceManagerFactory} at the JNDI
1752 * location specified by <code>jndiLocation</code> in the context
1753 * <code>context</code>. If <code>context</code> is
1754 * <code>null</code>, <code>new InitialContext()</code> will be
1755 * used. Creates a {@link PersistenceManagerFactory} with
1756 * <code>loader</code>. Any <code>NamingException</code>s thrown
1757 * will be wrapped in a {@link JDOFatalUserException}.
1758 * @since 2.0
1759 * @param jndiLocation the JNDI location containing the
1760 * PersistenceManagerFactory
1761 * @param context the context in which to find the named
1762 * PersistenceManagerFactory
1763 * @param loader the class loader to use to load the
1764 * <code>PersistenceManagerFactory</code> class
1765 * @return the PersistenceManagerFactory
1766 */
1767 public static PersistenceManagerFactory getPersistenceManagerFactory
1768 (String jndiLocation, Context context, ClassLoader loader) {
1769 if (jndiLocation == null)
1770 throw new JDOFatalUserException (msg.msg (
1771 "EXC_GetPMFNullJndiLoc"));
1772 if (loader == null)
1773 throw new JDOFatalUserException (msg.msg (
1774 "EXC_GetPMFNullLoader"));
1775 try {
1776 if (context == null)
1777 context = new InitialContext ();
1778
1779 Object o = context.lookup (jndiLocation);
1780 return (PersistenceManagerFactory) PortableRemoteObject.narrow
1781 (o, PersistenceManagerFactory.class);
1782 } catch (NamingException ne) {
1783 throw new JDOFatalUserException (msg.msg (
1784 "EXC_GetPMFNamingException", jndiLocation, loader), ne);
1785 }
1786 }
1787
1788 /**
1789 * Returns a {@link PersistenceManagerFactory} configured based
1790 * on the Properties stored in the input stream at
1791 * <code>stream</code>. This method is equivalent to
1792 * invoking {@link
1793 * #getPersistenceManagerFactory(InputStream,ClassLoader)} with
1794 * <code>Thread.currentThread().getContextClassLoader()</code> as
1795 * the <code>loader</code> argument.
1796 * @since 2.0
1797 * @param stream the stream containing the Properties
1798 * @return the PersistenceManagerFactory
1799 */
1800 public static PersistenceManagerFactory getPersistenceManagerFactory
1801 (InputStream stream) {
1802 return getPersistenceManagerFactory(
1803 stream, getContextClassLoader());
1804 }
1805
1806 /**
1807 * Returns a {@link PersistenceManagerFactory} configured based
1808 * on the Properties stored in the input stream at
1809 * <code>stream</code>. Creates a {@link
1810 * PersistenceManagerFactory} with <code>loader</code>. Any
1811 * <code>IOException</code>s thrown during resource
1812 * loading will be wrapped in a {@link JDOFatalUserException}.
1813 * @since 2.0
1814 * @param stream the stream containing the Properties
1815 * @param loader the class loader to use to load the
1816 * <code>PersistenceManagerFactory</code> class
1817 * @return the PersistenceManagerFactory
1818 */
1819 public static PersistenceManagerFactory getPersistenceManagerFactory
1820 (InputStream stream, ClassLoader loader) {
1821 if (stream == null)
1822 throw new JDOFatalUserException (msg.msg (
1823 "EXC_GetPMFNullStream"));
1824
1825 Properties props = new Properties ();
1826 try {
1827 props.load (stream);
1828 } catch (IOException ioe) {
1829 throw new JDOFatalUserException
1830 (msg.msg ("EXC_GetPMFIOExceptionStream"), ioe);
1831 }
1832 return getPersistenceManagerFactory (props, loader);
1833 }
1834
1835 /**
1836 * Get a <code>JDOEnhancer</code> using the available enhancer(s) specified in
1837 * "META-INF/services/JDOEnhancer" using the context class loader.
1838 * @return the <code>JDOEnhancer</code>.
1839 * @throws JDOFatalUserException if no available enhancer
1840 * @since 3.0
1841 */
1842 public static JDOEnhancer getEnhancer() {
1843 return getEnhancer(getContextClassLoader());
1844 }
1845
1846 /**
1847 * Get a <code>JDOEnhancer</code> using the available enhancer(s) specified in
1848 * "META-INF/services/JDOEnhancer"
1849 * @param loader the loader to use for loading the JDOEnhancer class (if any)
1850 * @return the <code>JDOEnhancer</code>.
1851 * @throws JDOFatalUserException if no available enhancer
1852 * @since 3.0
1853 */
1854 public static JDOEnhancer getEnhancer(ClassLoader loader) {
1855 ClassLoader ctrLoader = loader;
1856 if (ctrLoader == null) {
1857 ctrLoader = Thread.currentThread().getContextClassLoader();
1858 }
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871 ArrayList<Throwable> exceptions = new ArrayList<Throwable>();
1872 int numberOfJDOEnhancers = 0;
1873 try {
1874 Enumeration<URL> urls = getResources(loader, SERVICE_LOOKUP_ENHANCER_RESOURCE_NAME);
1875 if (urls != null) {
1876 while (urls.hasMoreElements()) {
1877 numberOfJDOEnhancers++;
1878 try {
1879 String enhancerClassName = getClassNameFromURL((URL)urls.nextElement());
1880 Class<?> enhancerClass = forName(enhancerClassName, true, ctrLoader);
1881 JDOEnhancer enhancer = (JDOEnhancer)enhancerClass.newInstance();
1882 return enhancer;
1883 } catch (Throwable ex) {
1884
1885 exceptions.add(ex);
1886 }
1887 }
1888 }
1889 } catch (Throwable ex) {
1890 exceptions.add(ex);
1891 }
1892
1893 throw new JDOFatalUserException(msg.msg("EXC_GetEnhancerNoValidEnhancerAvailable", numberOfJDOEnhancers),
1894 (Throwable[])exceptions.toArray(new Throwable[exceptions.size()]));
1895 }
1896
1897 /** Get the context class loader associated with the current thread.
1898 * This is done in a doPrivileged block because it is a secure method.
1899 * @return the current thread's context class loader.
1900 * @since 2.0
1901 */
1902 private static ClassLoader getContextClassLoader() {
1903 return AccessController.doPrivileged(
1904 new PrivilegedAction<ClassLoader> () {
1905 public ClassLoader run () {
1906 return Thread.currentThread().getContextClassLoader();
1907 }
1908 }
1909 );
1910 }
1911
1912 /** Get the named resource as a stream from the resource loader.
1913 * Perform this operation in a doPrivileged block.
1914 */
1915 private static InputStream getResourceAsStream(
1916 final ClassLoader resourceLoader, final String name) {
1917 return AccessController.doPrivileged(
1918 new PrivilegedAction<InputStream>() {
1919 public InputStream run() {
1920 return resourceLoader.getResourceAsStream(name);
1921 }
1922 }
1923 );
1924 }
1925
1926
1927 /** Get the named Method from the named class.
1928 * Perform this operation in a doPrivileged block.
1929 *
1930 * @param implClass the class
1931 * @param methodName the name of the method
1932 * @param parameterTypes the parameter types of the method
1933 * @return the Method instance
1934 */
1935 private static Method getMethod(
1936 final Class<?> implClass,
1937 final String methodName,
1938 final Class<?>[] parameterTypes)
1939 throws NoSuchMethodException {
1940 try {
1941 return AccessController.doPrivileged(
1942 new PrivilegedExceptionAction<Method>() {
1943 public Method run() throws NoSuchMethodException {
1944 return implClass.getMethod(methodName, parameterTypes);
1945 }
1946 }
1947 );
1948 } catch (PrivilegedActionException ex) {
1949 throw (NoSuchMethodException)ex.getException();
1950 }
1951 }
1952
1953 /** Invoke the method.
1954 * Perform this operation in a doPrivileged block.
1955 */
1956 private static Object invoke(final Method method,
1957 final Object instance, final Object[] parameters)
1958 throws IllegalAccessException, InvocationTargetException {
1959 try {
1960 return (Object) AccessController.doPrivileged(
1961 new PrivilegedExceptionAction<Object>() {
1962 public Object run()
1963 throws IllegalAccessException,
1964 InvocationTargetException {
1965 return method.invoke (instance, parameters);
1966 }
1967 }
1968 );
1969 } catch (PrivilegedActionException ex) {
1970 Exception cause = (Exception)ex.getException();
1971 if (cause instanceof IllegalAccessException)
1972 throw (IllegalAccessException)cause;
1973 else
1974 throw (InvocationTargetException)cause;
1975 }
1976 }
1977
1978 /** Get resources of the resource loader.
1979 * Perform this operation in a doPrivileged block.
1980 * @param resourceLoader
1981 * @param resourceName
1982 * @return the resources
1983 */
1984 protected static Enumeration<URL> getResources(
1985 final ClassLoader resourceLoader,
1986 final String resourceName)
1987 throws IOException {
1988 try {
1989 return AccessController.doPrivileged(
1990 new PrivilegedExceptionAction<Enumeration<URL>>() {
1991 public Enumeration<URL> run() throws IOException {
1992 return resourceLoader.getResources(resourceName);
1993 }
1994 }
1995 );
1996 } catch (PrivilegedActionException ex) {
1997 throw (IOException)ex.getException();
1998 }
1999 }
2000
2001 /** Get the named class.
2002 * Perform this operation in a doPrivileged block.
2003 *
2004 * @param name the name of the class
2005 * @param init whether to initialize the class
2006 * @param loader which class loader to use
2007 * @return the class
2008 */
2009 private static Class<?> forName(
2010 final String name,
2011 final boolean init,
2012 final ClassLoader loader)
2013 throws ClassNotFoundException {
2014 try {
2015 return AccessController.doPrivileged(
2016 new PrivilegedExceptionAction<Class<?>>() {
2017 public Class<?> run() throws ClassNotFoundException {
2018 return Class.forName(name, init, loader);
2019 }
2020 }
2021 );
2022 } catch (PrivilegedActionException ex) {
2023 throw (ClassNotFoundException)ex.getException();
2024 }
2025 }
2026
2027 /** Open an input stream on the url.
2028 * Perform this operation in a doPrivileged block.
2029 *
2030 * @param url
2031 * @return the input stream
2032 */
2033 private static InputStream openStream(final URL url)
2034 throws IOException {
2035 try {
2036 return AccessController.doPrivileged(
2037 new PrivilegedExceptionAction<InputStream>() {
2038 public InputStream run() throws IOException {
2039 return url.openStream();
2040 }
2041 }
2042 );
2043 } catch (PrivilegedActionException ex) {
2044 throw (IOException)ex.getException();
2045 }
2046 }
2047
2048 }