/* * Copyright (c) 2004, 2013, 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.presentation.rmi ; import java.lang.reflect.InvocationHandler ; import java.lang.reflect.Proxy ; import java.lang.reflect.Method ; import org.omg.CORBA.portable.ObjectImpl ; import java.io.ObjectStreamException ; import java.io.Serializable ; import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator ; import com.sun.corba.se.spi.presentation.rmi.PresentationManager ; import com.sun.corba.se.spi.presentation.rmi.DynamicStub ; import com.sun.corba.se.spi.orbutil.proxy.LinkedInvocationHandler ; import com.sun.corba.se.spi.orbutil.proxy.InvocationHandlerFactory ; import com.sun.corba.se.spi.orbutil.proxy.DelegateInvocationHandlerImpl ; import com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandler ; import com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl ; import java.security.AccessController; import java.security.PrivilegedAction; public class InvocationHandlerFactoryImpl implements InvocationHandlerFactory { private final PresentationManager.ClassData classData ; private final PresentationManager pm ; private Class[] proxyInterfaces ; public InvocationHandlerFactoryImpl( PresentationManager pm, PresentationManager.ClassData classData ) { this.classData = classData ; this.pm = pm ; Class[] remoteInterfaces = classData.getIDLNameTranslator().getInterfaces() ; proxyInterfaces = new Class[ remoteInterfaces.length + 1 ] ; for (int ctr=0; ctr<remoteInterfaces.length; ctr++) proxyInterfaces[ctr] = remoteInterfaces[ctr] ; proxyInterfaces[remoteInterfaces.length] = DynamicStub.class ; } private class CustomCompositeInvocationHandlerImpl extends CompositeInvocationHandlerImpl implements LinkedInvocationHandler, Serializable { private transient DynamicStub stub ; public void setProxy( Proxy proxy ) { ((DynamicStubImpl)stub).setSelf( (DynamicStub)proxy ) ; } public Proxy getProxy() { return (Proxy)((DynamicStubImpl)stub).getSelf() ; } public CustomCompositeInvocationHandlerImpl( DynamicStub stub ) { this.stub = stub ; } /** Return the stub, which will actually be written to the stream. * It will be custom marshalled, with the actual writing done in * StubIORImpl. There is a corresponding readResolve method on * DynamicStubImpl which will re-create the full invocation * handler on read, and return the invocation handler on the * readResolve method. */ public Object writeReplace() throws ObjectStreamException { return stub ; } } public InvocationHandler getInvocationHandler() { final DynamicStub stub = new DynamicStubImpl( classData.getTypeIds() ) ; return getInvocationHandler( stub ) ; } // This is also used in DynamicStubImpl to implement readResolve. InvocationHandler getInvocationHandler( DynamicStub stub ) { // Create an invocation handler for the methods defined on DynamicStub, // which extends org.omg.CORBA.Object. This handler delegates all // calls directly to a DynamicStubImpl, which extends // org.omg.CORBA.portable.ObjectImpl. final InvocationHandler dynamicStubHandler = DelegateInvocationHandlerImpl.create( stub ) ; // Create an invocation handler that handles any remote interface // methods. final InvocationHandler stubMethodHandler = new StubInvocationHandlerImpl( pm, classData, stub ) ; // Create a composite handler that handles the DynamicStub interface // as well as the remote interfaces. final CompositeInvocationHandler handler = new CustomCompositeInvocationHandlerImpl( stub ) ; AccessController.doPrivileged(new PrivilegedAction<Void>() { @Override public Void run() { handler.addInvocationHandler( DynamicStub.class, dynamicStubHandler ) ; handler.addInvocationHandler( org.omg.CORBA.Object.class, dynamicStubHandler ) ; handler.addInvocationHandler( Object.class, dynamicStubHandler ) ; return null; } }); // If the method passed to invoke is not from DynamicStub or its superclasses, // it must be from an implemented interface, so we just handle // all of these with the stubMethodHandler. This used to be // done be adding explicit entries for stubMethodHandler for // each remote interface, but that does not work correctly // for abstract interfaces, since the graph analysis ignores // abstract interfaces in order to compute the type ids // correctly (see PresentationManagerImpl.NodeImpl.getChildren). // Rather than produce more graph traversal code to handle this // problem, we simply use a default. // This also points to a possible optimization: just use explict // checks for the three special classes, rather than a general // table lookup that usually fails. handler.setDefaultHandler( stubMethodHandler ) ; return handler ; } public Class[] getProxyInterfaces() { return proxyInterfaces ; } }