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 
  26 package com.sun.corba.se.impl.presentation.rmi ;
  27 
  28 import java.lang.reflect.InvocationHandler ;
  29 import java.lang.reflect.Proxy ;
  30 import java.lang.reflect.Method ;
  31 
  32 import org.omg.CORBA.portable.ObjectImpl ;
  33 
  34 import java.io.ObjectStreamException ;
  35 import java.io.Serializable ;
  36 
  37 import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator ;
  38 import com.sun.corba.se.spi.presentation.rmi.PresentationManager ;
  39 import com.sun.corba.se.spi.presentation.rmi.DynamicStub ;
  40 
  41 import com.sun.corba.se.spi.orbutil.proxy.LinkedInvocationHandler ;
  42 import com.sun.corba.se.spi.orbutil.proxy.InvocationHandlerFactory ;
  43 import com.sun.corba.se.spi.orbutil.proxy.DelegateInvocationHandlerImpl ;
  44 import com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandler ;
  45 import com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl ;
  46 import java.security.AccessController;
  47 import java.security.PrivilegedAction;
  48 
  49 public 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 }