| /* |
| * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package com.sun.corba.se.impl.interceptors; |
| |
| import org.omg.PortableInterceptor.Interceptor; |
| import org.omg.PortableInterceptor.ORBInitInfo; |
| import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName; |
| |
| import org.omg.CORBA.INTERNAL; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.lang.reflect.Array; |
| |
| import com.sun.corba.se.impl.logging.InterceptorsSystemException ; |
| |
| /** |
| * Provides a repository of registered Portable Interceptors, organized |
| * by type. This list is designed to be accessed as efficiently as |
| * possible during runtime, with the expense of added complexity during |
| * initialization and interceptor registration. The class is designed |
| * to easily allow for the addition of new interceptor types. |
| */ |
| public class InterceptorList { |
| |
| // Interceptor type list. If additional interceptors are needed, |
| // add additional types in numerical order (do not skip numbers), |
| // and update NUM_INTERCEPTOR_TYPES and classTypes accordingly. |
| // NUM_INTERCEPTOR_TYPES represents the number of interceptor |
| // types, so we know how many lists to maintain. |
| static final int INTERCEPTOR_TYPE_CLIENT = 0; |
| static final int INTERCEPTOR_TYPE_SERVER = 1; |
| static final int INTERCEPTOR_TYPE_IOR = 2; |
| |
| static final int NUM_INTERCEPTOR_TYPES = 3; |
| |
| // Array of class types for interceptors. This is used to create the |
| // appropriate array type for each interceptor type. These must |
| // match the indices of the constants declared above. |
| static final Class[] classTypes = { |
| org.omg.PortableInterceptor.ClientRequestInterceptor.class, |
| org.omg.PortableInterceptor.ServerRequestInterceptor.class, |
| org.omg.PortableInterceptor.IORInterceptor.class |
| }; |
| |
| // True if no further interceptors may be registered with this list. |
| private boolean locked = false; |
| private InterceptorsSystemException wrapper ; |
| |
| // List of interceptors currently registered. There are |
| // NUM_INTERCEPTOR_TYPES lists of registered interceptors. |
| // For example, interceptors[INTERCEPTOR_TYPE_CLIENT] contains an array |
| // of objects of type ClientRequestInterceptor. |
| private Interceptor[][] interceptors = |
| new Interceptor[NUM_INTERCEPTOR_TYPES][]; |
| |
| /** |
| * Creates a new Interceptor List. Constructor is package scope so |
| * only the ORB can create it. |
| */ |
| InterceptorList( InterceptorsSystemException wrapper ) { |
| this.wrapper = wrapper ; |
| // Create empty interceptors arrays for each type: |
| initInterceptorArrays(); |
| } |
| |
| /** |
| * Registers an interceptor of the given type into the interceptor list. |
| * The type is one of: |
| * <ul> |
| * <li>INTERCEPTOR_TYPE_CLIENT - ClientRequestInterceptor |
| * <li>INTERCEPTOR_TYPE_SERVER - ServerRequestInterceptor |
| * <li>INTERCEPTOR_TYPE_IOR - IORInterceptor |
| * </ul> |
| * |
| * @exception DuplicateName Thrown if an interceptor of the given |
| * name already exists for the given type. |
| */ |
| void register_interceptor( Interceptor interceptor, int type ) |
| throws DuplicateName |
| { |
| // If locked, deny any further addition of interceptors. |
| if( locked ) { |
| throw wrapper.interceptorListLocked() ; |
| } |
| |
| // Cache interceptor name: |
| String interceptorName = interceptor.name(); |
| boolean anonymous = interceptorName.equals( "" ); |
| boolean foundDuplicate = false; |
| Interceptor[] interceptorList = interceptors[type]; |
| |
| // If this is not an anonymous interceptor, |
| // search for an interceptor of the same name in this category: |
| if( !anonymous ) { |
| int size = interceptorList.length; |
| |
| // An O(n) search will suffice because register_interceptor is not |
| // likely to be called often. |
| for( int i = 0; i < size; i++ ) { |
| Interceptor in = (Interceptor)interceptorList[i]; |
| if( in.name().equals( interceptorName ) ) { |
| foundDuplicate = true; |
| break; |
| } |
| } |
| } |
| |
| if( !foundDuplicate ) { |
| growInterceptorArray( type ); |
| interceptors[type][interceptors[type].length-1] = interceptor; |
| } |
| else { |
| throw new DuplicateName( interceptorName ); |
| } |
| } |
| |
| /** |
| * Locks this interceptor list so that no more interceptors may be |
| * registered. This method is called after all interceptors are |
| * registered for security reasons. |
| */ |
| void lock() { |
| locked = true; |
| } |
| |
| /** |
| * Retrieves an array of interceptors of the given type. For efficiency, |
| * the type parameter is assumed to be valid. |
| */ |
| Interceptor[] getInterceptors( int type ) { |
| return interceptors[type]; |
| } |
| |
| /** |
| * Returns true if there is at least one interceptor of the given type, |
| * or false if not. |
| */ |
| boolean hasInterceptorsOfType( int type ) { |
| return interceptors[type].length > 0; |
| } |
| |
| /** |
| * Initializes all interceptors arrays to zero-length arrays of the |
| * correct type, based on the classTypes list. |
| */ |
| private void initInterceptorArrays() { |
| for( int type = 0; type < NUM_INTERCEPTOR_TYPES; type++ ) { |
| Class classType = classTypes[type]; |
| |
| // Create a zero-length array for each type: |
| interceptors[type] = |
| (Interceptor[])Array.newInstance( classType, 0 ); |
| } |
| } |
| |
| /** |
| * Grows the given interceptor array by one: |
| */ |
| private void growInterceptorArray( int type ) { |
| Class classType = classTypes[type]; |
| int currentLength = interceptors[type].length; |
| Interceptor[] replacementArray; |
| |
| // Create new array to replace the old one. The new array will be |
| // one element larger but have the same type as the old one. |
| replacementArray = (Interceptor[]) |
| Array.newInstance( classType, currentLength + 1 ); |
| System.arraycopy( interceptors[type], 0, |
| replacementArray, 0, currentLength ); |
| interceptors[type] = replacementArray; |
| } |
| |
| /** |
| * Destroys all interceptors in this list by invoking their destroy() |
| * method. |
| */ |
| void destroyAll() { |
| int numTypes = interceptors.length; |
| |
| for( int i = 0; i < numTypes; i++ ) { |
| int numInterceptors = interceptors[i].length; |
| for( int j = 0; j < numInterceptors; j++ ) { |
| interceptors[i][j].destroy(); |
| } |
| } |
| } |
| |
| /** |
| * Sort interceptors. |
| */ |
| void sortInterceptors() { |
| List sorted = null; |
| List unsorted = null; |
| |
| int numTypes = interceptors.length; |
| |
| for( int i = 0; i < numTypes; i++ ) { |
| int numInterceptors = interceptors[i].length; |
| if (numInterceptors > 0) { |
| // Get fresh sorting bins for each non empty type. |
| sorted = new ArrayList(); // not synchronized like we want. |
| unsorted = new ArrayList(); |
| } |
| for( int j = 0; j < numInterceptors; j++ ) { |
| Interceptor interceptor = interceptors[i][j]; |
| if (interceptor instanceof Comparable) { |
| sorted.add(interceptor); |
| } else { |
| unsorted.add(interceptor); |
| } |
| } |
| if (numInterceptors > 0 && sorted.size() > 0) { |
| // Let the RuntimeExceptions thrown by sort |
| // (i.e., ClassCastException and UnsupportedOperationException) |
| // flow back to the user. |
| Collections.sort(sorted); |
| Iterator sortedIterator = sorted.iterator(); |
| Iterator unsortedIterator = unsorted.iterator(); |
| for( int j = 0; j < numInterceptors; j++ ) { |
| if (sortedIterator.hasNext()) { |
| interceptors[i][j] = |
| (Interceptor) sortedIterator.next(); |
| } else if (unsortedIterator.hasNext()) { |
| interceptors[i][j] = |
| (Interceptor) unsortedIterator.next(); |
| } else { |
| throw wrapper.sortSizeMismatch() ; |
| } |
| } |
| } |
| } |
| } |
| } |