1. /*
  2. * @(#)FactoryEnumeration.java 1.8 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.naming.internal;
  8. import java.util.List;
  9. import javax.naming.NamingException;
  10. /**
  11. * The FactoryEnumeration is used for returning factory instances.
  12. *
  13. * @author Rosanna Lee
  14. * @author Scott Seligman
  15. * @version 1.8 03/12/19
  16. */
  17. // no need to implement Enumeration since this is only for internal use
  18. public final class FactoryEnumeration {
  19. private List factories;
  20. private int posn = 0;
  21. private ClassLoader loader;
  22. /**
  23. * Records the input list and uses it directly to satisfy
  24. * hasMore()/next() requests. An alternative would have been to use
  25. * an enumeration/iterator from the list, but we want to update the
  26. * list so we keep the
  27. * original list. The list initially contains Class objects.
  28. * As each element is used, the Class object is replaced by an
  29. * instance of the Class itself; eventually, the list contains
  30. * only a list of factory instances and no more updates are required.
  31. *
  32. * <p> Both Class objects and factories are wrapped in weak
  33. * references so as not to prevent GC of the class loader. Each
  34. * weak reference is tagged with the factory's class name so the
  35. * class can be reloaded if the reference is cleared.
  36. * @param factories A non-null list
  37. * @param loader The class loader of the list's contents
  38. */
  39. FactoryEnumeration(List factories, ClassLoader loader) {
  40. this.factories = factories;
  41. this.loader = loader;
  42. }
  43. public Object next() throws NamingException {
  44. synchronized (factories) {
  45. NamedWeakReference ref = (NamedWeakReference) factories.get(posn++);
  46. Object answer = ref.get();
  47. if ((answer != null) && !(answer instanceof Class)) {
  48. return answer;
  49. }
  50. String className = ref.getName();
  51. try {
  52. if (answer == null) { // reload class if weak ref cleared
  53. answer = Class.forName(className, true, loader);
  54. }
  55. // Instantiate Class to get factory
  56. answer = ((Class) answer).newInstance();
  57. ref = new NamedWeakReference(answer, className);
  58. factories.set(posn-1, ref); // replace Class object or null
  59. return answer;
  60. } catch (ClassNotFoundException e) {
  61. NamingException ne =
  62. new NamingException("No longer able to load " + className);
  63. ne.setRootCause(e);
  64. throw ne;
  65. } catch (InstantiationException e) {
  66. NamingException ne =
  67. new NamingException("Cannot instantiate " + answer);
  68. ne.setRootCause(e);
  69. throw ne;
  70. } catch (IllegalAccessException e) {
  71. NamingException ne = new NamingException("Cannot access " + answer);
  72. ne.setRootCause(e);
  73. throw ne;
  74. }
  75. }
  76. }
  77. public boolean hasMore() {
  78. synchronized (factories) {
  79. return posn < factories.size();
  80. }
  81. }
  82. }