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 |