src/share/classes/com/sun/naming/internal/FactoryEnumeration.java

Print this page




  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.naming.internal;
  27 
  28 import java.util.List;
  29 import javax.naming.NamingException;
  30 
  31 /**
  32   * The FactoryEnumeration is used for returning factory instances.
  33   *
  34   * @author Rosanna Lee
  35   * @author Scott Seligman
  36  */
  37 
  38 // no need to implement Enumeration since this is only for internal use
  39 public final class FactoryEnumeration {
  40     private List factories;

  41     private int posn = 0;
  42     private ClassLoader loader;
  43 
  44     /**
  45      * Records the input list and uses it directly to satisfy
  46      * hasMore()/next() requests. An alternative would have been to use
  47      * an enumeration/iterator from the list, but we want to update the
  48      * list so we keep the
  49      * original list. The list initially contains Class objects.
  50      * As each element is used, the Class object is replaced by an
  51      * instance of the Class itself; eventually, the list contains
  52      * only a list of factory instances and no more updates are required.
  53      *
  54      * <p> Both Class objects and factories are wrapped in weak
  55      * references so as not to prevent GC of the class loader.  Each
  56      * weak reference is tagged with the factory's class name so the
  57      * class can be reloaded if the reference is cleared.
  58 
  59      * @param factories A non-null list
  60      * @param loader    The class loader of the list's contents
  61      */
  62     FactoryEnumeration(List factories, ClassLoader loader) {

  63         this.factories = factories;
  64         this.loader = loader;
  65     }
  66 
  67     public Object next() throws NamingException {
  68         synchronized (factories) {
  69 
  70             NamedWeakReference ref = (NamedWeakReference) factories.get(posn++);
  71             Object answer = ref.get();
  72             if ((answer != null) && !(answer instanceof Class)) {
  73                 return answer;
  74             }
  75 
  76             String className = ref.getName();
  77 
  78             try {
  79                 if (answer == null) {   // reload class if weak ref cleared
  80                     answer = Class.forName(className, true, loader);
  81                 }
  82                 // Instantiate Class to get factory
  83                 answer = ((Class) answer).newInstance();
  84                 ref = new NamedWeakReference(answer, className);
  85                 factories.set(posn-1, ref);  // replace Class object or null
  86                 return answer;
  87             } catch (ClassNotFoundException e) {
  88                 NamingException ne =
  89                     new NamingException("No longer able to load " + className);
  90                 ne.setRootCause(e);
  91                 throw ne;
  92             } catch (InstantiationException e) {
  93                 NamingException ne =
  94                     new NamingException("Cannot instantiate " + answer);
  95                 ne.setRootCause(e);
  96                 throw ne;
  97             } catch (IllegalAccessException e) {
  98                 NamingException ne = new NamingException("Cannot access " + answer);
  99                 ne.setRootCause(e);
 100                 throw ne;
 101             }
 102         }
 103     }
 104 


  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.naming.internal;
  27 
  28 import java.util.List;
  29 import javax.naming.NamingException;
  30 
  31 /**
  32   * The FactoryEnumeration is used for returning factory instances.
  33   *
  34   * @author Rosanna Lee
  35   * @author Scott Seligman
  36  */
  37 
  38 // no need to implement Enumeration since this is only for internal use
  39 public final class FactoryEnumeration {
  40     // List<NamedWeakReference<Class | Object>>
  41     private List<NamedWeakReference<Object>> factories;
  42     private int posn = 0;
  43     private ClassLoader loader;
  44 
  45     /**
  46      * Records the input list and uses it directly to satisfy
  47      * hasMore()/next() requests. An alternative would have been to use
  48      * an enumeration/iterator from the list, but we want to update the
  49      * list so we keep the
  50      * original list. The list initially contains Class objects.
  51      * As each element is used, the Class object is replaced by an
  52      * instance of the Class itself; eventually, the list contains
  53      * only a list of factory instances and no more updates are required.
  54      *
  55      * <p> Both Class objects and factories are wrapped in weak
  56      * references so as not to prevent GC of the class loader.  Each
  57      * weak reference is tagged with the factory's class name so the
  58      * class can be reloaded if the reference is cleared.
  59 
  60      * @param factories A non-null list
  61      * @param loader    The class loader of the list's contents
  62      */
  63     FactoryEnumeration(List<NamedWeakReference<Object>> factories,
  64                        ClassLoader loader) {
  65         this.factories = factories;
  66         this.loader = loader;
  67     }
  68 
  69     public Object next() throws NamingException {
  70         synchronized (factories) {
  71 
  72             NamedWeakReference<Object> ref = factories.get(posn++);
  73             Object answer = ref.get();
  74             if ((answer != null) && !(answer instanceof Class)) {
  75                 return answer;
  76             }
  77 
  78             String className = ref.getName();
  79 
  80             try {
  81                 if (answer == null) {   // reload class if weak ref cleared
  82                     answer = Class.forName(className, true, loader);
  83                 }
  84                 // Instantiate Class to get factory
  85                 answer = ((Class) answer).newInstance();
  86                 ref = new NamedWeakReference<>(answer, className);
  87                 factories.set(posn-1, ref);  // replace Class object or null
  88                 return answer;
  89             } catch (ClassNotFoundException e) {
  90                 NamingException ne =
  91                     new NamingException("No longer able to load " + className);
  92                 ne.setRootCause(e);
  93                 throw ne;
  94             } catch (InstantiationException e) {
  95                 NamingException ne =
  96                     new NamingException("Cannot instantiate " + answer);
  97                 ne.setRootCause(e);
  98                 throw ne;
  99             } catch (IllegalAccessException e) {
 100                 NamingException ne = new NamingException("Cannot access " + answer);
 101                 ne.setRootCause(e);
 102                 throw ne;
 103             }
 104         }
 105     }
 106