InvocationHandlerFactoryImpl.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 2004, 2013, 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.presentation.rmi ;
27
28import java.lang.reflect.InvocationHandler ;
29import java.lang.reflect.Proxy ;
30import java.lang.reflect.Method ;
31
32import org.omg.CORBA.portable.ObjectImpl ;
33
34import java.io.ObjectStreamException ;
35import java.io.Serializable ;
36
37import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator ;
38import com.sun.corba.se.spi.presentation.rmi.PresentationManager ;
39import com.sun.corba.se.spi.presentation.rmi.DynamicStub ;
40
41import com.sun.corba.se.spi.orbutil.proxy.LinkedInvocationHandler ;
42import com.sun.corba.se.spi.orbutil.proxy.InvocationHandlerFactory ;
43import com.sun.corba.se.spi.orbutil.proxy.DelegateInvocationHandlerImpl ;
44import com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandler ;
45import com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl ;
46import java.security.AccessController;
47import java.security.PrivilegedAction;
48
49public class InvocationHandlerFactoryImpl implements InvocationHandlerFactory
50{
51    private final PresentationManager.ClassData classData ;
52    private final PresentationManager pm ;
53    private Class[] proxyInterfaces ;
54
55    public InvocationHandlerFactoryImpl( PresentationManager pm,
56        PresentationManager.ClassData classData )
57    {
58        this.classData = classData ;
59        this.pm = pm ;
60
61        Class[] remoteInterfaces =
62            classData.getIDLNameTranslator().getInterfaces() ;
63        proxyInterfaces = new Class[ remoteInterfaces.length + 1 ] ;
64        for (int ctr=0; ctr<remoteInterfaces.length; ctr++)
65            proxyInterfaces[ctr] = remoteInterfaces[ctr] ;
66
67        proxyInterfaces[remoteInterfaces.length] = DynamicStub.class ;
68    }
69
70    private class CustomCompositeInvocationHandlerImpl extends
71        CompositeInvocationHandlerImpl implements LinkedInvocationHandler,
72        Serializable
73    {
74        private transient DynamicStub stub ;
75
76        public void setProxy( Proxy proxy )
77        {
78            ((DynamicStubImpl)stub).setSelf( (DynamicStub)proxy ) ;
79        }
80
81        public Proxy getProxy()
82        {
83            return (Proxy)((DynamicStubImpl)stub).getSelf() ;
84        }
85
86        public CustomCompositeInvocationHandlerImpl( DynamicStub stub )
87        {
88            this.stub = stub ;
89        }
90
91        /** Return the stub, which will actually be written to the stream.
92         * It will be custom marshalled, with the actual writing done in
93         * StubIORImpl.  There is a corresponding readResolve method on
94         * DynamicStubImpl which will re-create the full invocation
95         * handler on read, and return the invocation handler on the
96         * readResolve method.
97         */
98        public Object writeReplace() throws ObjectStreamException
99        {
100            return stub ;
101        }
102    }
103
104    public InvocationHandler getInvocationHandler()
105    {
106        final DynamicStub stub = new DynamicStubImpl(
107            classData.getTypeIds() ) ;
108
109        return getInvocationHandler( stub ) ;
110    }
111
112    // This is also used in DynamicStubImpl to implement readResolve.
113    InvocationHandler getInvocationHandler( DynamicStub stub )
114    {
115        // Create an invocation handler for the methods defined on DynamicStub,
116        // which extends org.omg.CORBA.Object.  This handler delegates all
117        // calls directly to a DynamicStubImpl, which extends
118        // org.omg.CORBA.portable.ObjectImpl.
119        final InvocationHandler dynamicStubHandler =
120            DelegateInvocationHandlerImpl.create( stub ) ;
121
122        // Create an invocation handler that handles any remote interface
123        // methods.
124        final InvocationHandler stubMethodHandler = new StubInvocationHandlerImpl(
125            pm, classData, stub ) ;
126
127        // Create a composite handler that handles the DynamicStub interface
128        // as well as the remote interfaces.
129        final CompositeInvocationHandler handler =
130            new CustomCompositeInvocationHandlerImpl( stub ) ;
131
132        AccessController.doPrivileged(new PrivilegedAction<Void>() {
133            @Override
134            public Void run() {
135        handler.addInvocationHandler( DynamicStub.class,
136            dynamicStubHandler ) ;
137        handler.addInvocationHandler( org.omg.CORBA.Object.class,
138            dynamicStubHandler ) ;
139        handler.addInvocationHandler( Object.class,
140            dynamicStubHandler ) ;
141                return null;
142            }
143        });
144
145
146        // If the method passed to invoke is not from DynamicStub or its superclasses,
147        // it must be from an implemented interface, so we just handle
148        // all of these with the stubMethodHandler.  This used to be
149        // done be adding explicit entries for stubMethodHandler for
150        // each remote interface, but that does not work correctly
151        // for abstract interfaces, since the graph analysis ignores
152        // abstract interfaces in order to compute the type ids
153        // correctly (see PresentationManagerImpl.NodeImpl.getChildren).
154        // Rather than produce more graph traversal code to handle this
155        // problem, we simply use a default.
156        // This also points to a possible optimization: just use explict
157        // checks for the three special classes, rather than a general
158        // table lookup that usually fails.
159        handler.setDefaultHandler( stubMethodHandler ) ;
160
161        return handler ;
162    }
163
164    public Class[] getProxyInterfaces()
165    {
166        return proxyInterfaces ;
167    }
168}
169