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