1. /*
  2. * @(#)InterceptorList.java 1.16 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.internal.Interceptors;
  8. import org.omg.PortableInterceptor.Interceptor;
  9. import org.omg.PortableInterceptor.ORBInitInfo;
  10. import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName;
  11. import org.omg.CORBA.INTERNAL;
  12. import java.util.ArrayList;
  13. import java.util.Collection;
  14. import java.util.Collections;
  15. import java.util.Iterator;
  16. import java.util.List;
  17. import java.lang.reflect.Array;
  18. /**
  19. * Provides a repository of registered Portable Interceptors, organized
  20. * by type. This list is designed to be accessed as efficiently as
  21. * possible during runtime, with the expense of added complexity during
  22. * initialization and interceptor registration. The class is designed
  23. * to easily allow for the addition of new interceptor types.
  24. */
  25. public class InterceptorList {
  26. // Interceptor type list. If additional interceptors are needed,
  27. // add additional types in numerical order (do not skip numbers),
  28. // and update NUM_INTERCEPTOR_TYPES and classTypes accordingly.
  29. // NUM_INTERCEPTOR_TYPES represents the number of interceptor
  30. // types, so we know how many lists to maintain.
  31. static final int INTERCEPTOR_TYPE_CLIENT = 0;
  32. static final int INTERCEPTOR_TYPE_SERVER = 1;
  33. static final int INTERCEPTOR_TYPE_IOR = 2;
  34. static final int NUM_INTERCEPTOR_TYPES = 3;
  35. // Array of class types for interceptors. This is used to create the
  36. // appropriate array type for each interceptor type. These must
  37. // match the indices of the constants declared above.
  38. static final Class[] classTypes = {
  39. org.omg.PortableInterceptor.ClientRequestInterceptor.class,
  40. org.omg.PortableInterceptor.ServerRequestInterceptor.class,
  41. org.omg.PortableInterceptor.IORInterceptor.class
  42. };
  43. // True if no further interceptors may be registered with this list.
  44. private boolean locked = false;
  45. // List of interceptors currently registered. There are
  46. // NUM_INTERCEPTOR_TYPES lists of registered interceptors.
  47. // For example, interceptors[INTERCEPTOR_TYPE_CLIENT] contains an array
  48. // of objects of type ClientRequestInterceptor.
  49. private Interceptor[][] interceptors =
  50. new Interceptor[NUM_INTERCEPTOR_TYPES][];
  51. /**
  52. * Creates a new Interceptor List. Constructor is package scope so
  53. * only the ORB can create it.
  54. */
  55. InterceptorList() {
  56. // Create empty interceptors arrays for each type:
  57. initInterceptorArrays();
  58. }
  59. /**
  60. * Registers an interceptor of the given type into the interceptor list.
  61. * The type is one of:
  62. * <ul>
  63. * <li>INTERCEPTOR_TYPE_CLIENT - ClientRequestInterceptor
  64. * <li>INTERCEPTOR_TYPE_SERVER - ServerRequestInterceptor
  65. * <li>INTERCEPTOR_TYPE_IOR - IORInterceptor
  66. * </ul>
  67. *
  68. * @exception DuplicateName Thrown if an interceptor of the given
  69. * name already exists for the given type.
  70. */
  71. void register_interceptor( Interceptor interceptor, int type )
  72. throws DuplicateName
  73. {
  74. // If locked, deny any further addition of interceptors.
  75. if( locked ) {
  76. throw new INTERNAL( "InterceptorList is locked." );
  77. }
  78. // Cache interceptor name:
  79. String interceptorName = interceptor.name();
  80. boolean anonymous = interceptorName.equals( "" );
  81. boolean foundDuplicate = false;
  82. Interceptor[] interceptorList = interceptors[type];
  83. // If this is not an anonymous interceptor,
  84. // search for an interceptor of the same name in this category:
  85. if( !anonymous ) {
  86. int size = interceptorList.length;
  87. // An O(n) search will suffice because register_interceptor is not
  88. // likely to be called often.
  89. for( int i = 0; i < size; i++ ) {
  90. Interceptor in = (Interceptor)interceptorList[i];
  91. if( in.name().equals( interceptorName ) ) {
  92. foundDuplicate = true;
  93. break;
  94. }
  95. }
  96. }
  97. if( !foundDuplicate ) {
  98. growInterceptorArray( type );
  99. interceptors[type][interceptors[type].length-1] = interceptor;
  100. }
  101. else {
  102. throw new DuplicateName( interceptorName );
  103. }
  104. }
  105. /**
  106. * Locks this interceptor list so that no more interceptors may be
  107. * registered. This method is called after all interceptors are
  108. * registered for security reasons.
  109. */
  110. void lock() {
  111. locked = true;
  112. }
  113. /**
  114. * Retrieves an array of interceptors of the given type. For efficiency,
  115. * the type parameter is assumed to be valid.
  116. */
  117. Interceptor[] getInterceptors( int type ) {
  118. return interceptors[type];
  119. }
  120. /**
  121. * Returns true if there is at least one interceptor of the given type,
  122. * or false if not.
  123. */
  124. boolean hasInterceptorsOfType( int type ) {
  125. return interceptors[type].length > 0;
  126. }
  127. /**
  128. * Initializes all interceptors arrays to zero-length arrays of the
  129. * correct type, based on the classTypes list.
  130. */
  131. private void initInterceptorArrays() {
  132. for( int type = 0; type < NUM_INTERCEPTOR_TYPES; type++ ) {
  133. Class classType = classTypes[type];
  134. // Create a zero-length array for each type:
  135. interceptors[type] =
  136. (Interceptor[])Array.newInstance( classType, 0 );
  137. }
  138. }
  139. /**
  140. * Grows the given interceptor array by one:
  141. */
  142. private void growInterceptorArray( int type ) {
  143. Class classType = classTypes[type];
  144. int currentLength = interceptors[type].length;
  145. Interceptor[] replacementArray;
  146. // Create new array to replace the old one. The new array will be
  147. // one element larger but have the same type as the old one.
  148. replacementArray = (Interceptor[])
  149. Array.newInstance( classType, currentLength + 1 );
  150. System.arraycopy( interceptors[type], 0,
  151. replacementArray, 0, currentLength );
  152. interceptors[type] = replacementArray;
  153. }
  154. /**
  155. * Destroys all interceptors in this list by invoking their destroy()
  156. * method.
  157. */
  158. void destroyAll() {
  159. int numTypes = interceptors.length;
  160. for( int i = 0; i < numTypes; i++ ) {
  161. int numInterceptors = interceptors[i].length;
  162. for( int j = 0; j < numInterceptors; j++ ) {
  163. interceptors[i][j].destroy();
  164. }
  165. }
  166. }
  167. /**
  168. * Sort interceptors.
  169. */
  170. void sortInterceptors() {
  171. List sorted = null;
  172. List unsorted = null;
  173. int numTypes = interceptors.length;
  174. for( int i = 0; i < numTypes; i++ ) {
  175. int numInterceptors = interceptors[i].length;
  176. if (numInterceptors > 0) {
  177. // Get fresh sorting bins for each non empty type.
  178. sorted = new ArrayList(); // not synchronized like we want.
  179. unsorted = new ArrayList();
  180. }
  181. for( int j = 0; j < numInterceptors; j++ ) {
  182. Interceptor interceptor = interceptors[i][j];
  183. if (interceptor instanceof Comparable) {
  184. sorted.add(interceptor);
  185. } else {
  186. unsorted.add(interceptor);
  187. }
  188. }
  189. if (numInterceptors > 0 && sorted.size() > 0) {
  190. // Let the RuntimeExceptions thrown by sort
  191. // (i.e., ClassCastException and UnsupportedOperationException)
  192. // flow back to the user.
  193. Collections.sort(sorted);
  194. Iterator sortedIterator = sorted.iterator();
  195. Iterator unsortedIterator = unsorted.iterator();
  196. for( int j = 0; j < numInterceptors; j++ ) {
  197. if (sortedIterator.hasNext()) {
  198. interceptors[i][j] =
  199. (Interceptor) sortedIterator.next();
  200. } else if (unsortedIterator.hasNext()) {
  201. interceptors[i][j] =
  202. (Interceptor) unsortedIterator.next();
  203. } else {
  204. throw new INTERNAL("InterceptorList.sortInterceptors");
  205. }
  206. }
  207. }
  208. }
  209. }
  210. }