blob: b8e6466f8665004682beae2e330f5dcef001fad7 [file] [log] [blame]
/*
* 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() ;
}
}
}
}
}
}