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