InterceptorList.java revision 608:7e06bf1dcb09
1281760Ssjg/*
2281760Ssjg * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
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
26package com.sun.corba.se.impl.interceptors;
27
28import org.omg.PortableInterceptor.Interceptor;
29import org.omg.PortableInterceptor.ORBInitInfo;
30import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName;
31
32import org.omg.CORBA.INTERNAL;
33
34import java.util.ArrayList;
35import java.util.Collection;
36import java.util.Collections;
37import java.util.Iterator;
38import java.util.List;
39import java.lang.reflect.Array;
40
41import com.sun.corba.se.impl.logging.InterceptorsSystemException ;
42
43/**
44 * Provides a repository of registered Portable Interceptors, organized
45 * by type.  This list is designed to be accessed as efficiently as
46 * possible during runtime, with the expense of added complexity during
47 * initialization and interceptor registration.  The class is designed
48 * to easily allow for the addition of new interceptor types.
49 */
50public class InterceptorList {
51
52    // Interceptor type list.  If additional interceptors are needed,
53    // add additional types in numerical order (do not skip numbers),
54    // and update NUM_INTERCEPTOR_TYPES and classTypes accordingly.
55    // NUM_INTERCEPTOR_TYPES represents the number of interceptor
56    // types, so we know how many lists to maintain.
57    static final int INTERCEPTOR_TYPE_CLIENT            = 0;
58    static final int INTERCEPTOR_TYPE_SERVER            = 1;
59    static final int INTERCEPTOR_TYPE_IOR               = 2;
60
61    static final int NUM_INTERCEPTOR_TYPES              = 3;
62
63    // Array of class types for interceptors.  This is used to create the
64    // appropriate array type for each interceptor type.  These must
65    // match the indices of the constants declared above.
66    static final Class[] classTypes = {
67        org.omg.PortableInterceptor.ClientRequestInterceptor.class,
68        org.omg.PortableInterceptor.ServerRequestInterceptor.class,
69        org.omg.PortableInterceptor.IORInterceptor.class
70    };
71
72    // True if no further interceptors may be registered with this list.
73    private boolean locked = false;
74    private InterceptorsSystemException wrapper ;
75
76    // List of interceptors currently registered.  There are
77    // NUM_INTERCEPTOR_TYPES lists of registered interceptors.
78    // For example, interceptors[INTERCEPTOR_TYPE_CLIENT] contains an array
79    // of objects of type ClientRequestInterceptor.
80    private Interceptor[][] interceptors =
81        new Interceptor[NUM_INTERCEPTOR_TYPES][];
82
83    /**
84     * Creates a new Interceptor List.  Constructor is package scope so
85     * only the ORB can create it.
86     */
87    InterceptorList( InterceptorsSystemException wrapper ) {
88        this.wrapper = wrapper ;
89        // Create empty interceptors arrays for each type:
90        initInterceptorArrays();
91    }
92
93    /**
94     * Registers an interceptor of the given type into the interceptor list.
95     * The type is one of:
96     * <ul>
97     *   <li>INTERCEPTOR_TYPE_CLIENT - ClientRequestInterceptor
98     *   <li>INTERCEPTOR_TYPE_SERVER - ServerRequestInterceptor
99     *   <li>INTERCEPTOR_TYPE_IOR - IORInterceptor
100     * </ul>
101     *
102     * @exception DuplicateName Thrown if an interceptor of the given
103     *     name already exists for the given type.
104     */
105    void register_interceptor( Interceptor interceptor, int type )
106        throws DuplicateName
107    {
108        // If locked, deny any further addition of interceptors.
109        if( locked ) {
110            throw wrapper.interceptorListLocked() ;
111        }
112
113        // Cache interceptor name:
114        String interceptorName = interceptor.name();
115        boolean anonymous = interceptorName.equals( "" );
116        boolean foundDuplicate = false;
117        Interceptor[] interceptorList = interceptors[type];
118
119        // If this is not an anonymous interceptor,
120        // search for an interceptor of the same name in this category:
121        if( !anonymous ) {
122            int size = interceptorList.length;
123
124            // An O(n) search will suffice because register_interceptor is not
125            // likely to be called often.
126            for( int i = 0; i < size; i++ ) {
127                Interceptor in = (Interceptor)interceptorList[i];
128                if( in.name().equals( interceptorName ) ) {
129                    foundDuplicate = true;
130                    break;
131                }
132            }
133        }
134
135        if( !foundDuplicate ) {
136            growInterceptorArray( type );
137            interceptors[type][interceptors[type].length-1] = interceptor;
138        }
139        else {
140            throw new DuplicateName( interceptorName );
141        }
142    }
143
144    /**
145     * Locks this interceptor list so that no more interceptors may be
146     * registered.  This method is called after all interceptors are
147     * registered for security reasons.
148     */
149    void lock() {
150        locked = true;
151    }
152
153    /**
154     * Retrieves an array of interceptors of the given type.  For efficiency,
155     * the type parameter is assumed to be valid.
156     */
157    Interceptor[] getInterceptors( int type ) {
158        return interceptors[type];
159    }
160
161    /**
162     * Returns true if there is at least one interceptor of the given type,
163     * or false if not.
164     */
165    boolean hasInterceptorsOfType( int type ) {
166        return interceptors[type].length > 0;
167    }
168
169    /**
170     * Initializes all interceptors arrays to zero-length arrays of the
171     * correct type, based on the classTypes list.
172     */
173    private void initInterceptorArrays() {
174        for( int type = 0; type < NUM_INTERCEPTOR_TYPES; type++ ) {
175            Class classType = classTypes[type];
176
177            // Create a zero-length array for each type:
178            interceptors[type] =
179                (Interceptor[])Array.newInstance( classType, 0 );
180        }
181    }
182
183    /**
184     * Grows the given interceptor array by one:
185     */
186    private void growInterceptorArray( int type ) {
187        Class classType = classTypes[type];
188        int currentLength = interceptors[type].length;
189        Interceptor[] replacementArray;
190
191        // Create new array to replace the old one.  The new array will be
192        // one element larger but have the same type as the old one.
193        replacementArray = (Interceptor[])
194            Array.newInstance( classType, currentLength + 1 );
195        System.arraycopy( interceptors[type], 0,
196                          replacementArray, 0, currentLength );
197        interceptors[type] = replacementArray;
198    }
199
200    /**
201     * Destroys all interceptors in this list by invoking their destroy()
202     * method.
203     */
204    void destroyAll() {
205        int numTypes = interceptors.length;
206
207        for( int i = 0; i < numTypes; i++ ) {
208            int numInterceptors = interceptors[i].length;
209            for( int j = 0; j < numInterceptors; j++ ) {
210                interceptors[i][j].destroy();
211            }
212        }
213    }
214
215    /**
216     * Sort interceptors.
217     */
218    void sortInterceptors() {
219        List sorted = null;
220        List unsorted = null;
221
222        int numTypes = interceptors.length;
223
224        for( int i = 0; i < numTypes; i++ ) {
225            int numInterceptors = interceptors[i].length;
226            if (numInterceptors > 0) {
227                // Get fresh sorting bins for each non empty type.
228                sorted = new ArrayList(); // not synchronized like we want.
229                unsorted = new ArrayList();
230            }
231            for( int j = 0; j < numInterceptors; j++ ) {
232                Interceptor interceptor = interceptors[i][j];
233                if (interceptor instanceof Comparable) {
234                    sorted.add(interceptor);
235                } else {
236                    unsorted.add(interceptor);
237                }
238            }
239            if (numInterceptors > 0 && sorted.size() > 0) {
240                // Let the RuntimeExceptions thrown by sort
241                // (i.e., ClassCastException and UnsupportedOperationException)
242                // flow back to the user.
243                Collections.sort(sorted);
244                Iterator sortedIterator = sorted.iterator();
245                Iterator unsortedIterator = unsorted.iterator();
246                for( int j = 0; j < numInterceptors; j++ ) {
247                    if (sortedIterator.hasNext()) {
248                        interceptors[i][j] =
249                            (Interceptor) sortedIterator.next();
250                    } else if (unsortedIterator.hasNext()) {
251                        interceptors[i][j] =
252                            (Interceptor) unsortedIterator.next();
253                    } else {
254                        throw wrapper.sortSizeMismatch() ;
255                    }
256                }
257            }
258        }
259    }
260}
261