1 /*
   2  * Copyright (c) 2004, 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.Field ;
  29 
  30 import java.util.Hashtable;
  31 
  32 import javax.naming.*;
  33 import javax.naming.spi.StateFactory;
  34 
  35 import java.security.AccessController ;
  36 import java.security.PrivilegedAction ;
  37 
  38 import javax.rmi.PortableRemoteObject ;
  39 
  40 import com.sun.corba.se.spi.orb.ORB;
  41 
  42 import java.rmi.Remote;
  43 import java.rmi.server.ExportException;
  44 
  45 // XXX This creates a dependendcy on the implementation
  46 // of the CosNaming service provider.
  47 import com.sun.jndi.cosnaming.CNCtx ;
  48 
  49 import com.sun.corba.se.spi.presentation.rmi.StubAdapter ;
  50 
  51 /**
  52   * StateFactory that turns java.rmi.Remote objects to org.omg.CORBA.Object.
  53   * This version works either with standard RMI-IIOP or Dynamic RMI-IIOP.
  54   * Based on the original com.sun.jndi.cosnaming.RemoteToCorba and
  55   * com.sun.jndi.toolkit.corba.CorbaUtils.
  56   *
  57   * @author Ken Cavanaugh
  58   */
  59 
  60 public class JNDIStateFactoryImpl implements StateFactory
  61 {
  62     private static final Field orbField ;
  63 
  64     static {
  65         orbField = (Field) AccessController.doPrivileged(
  66             new PrivilegedAction() {
  67                 public Object run() {
  68                     Field fld = null ;
  69                     try {
  70                         Class cls = CNCtx.class ;
  71                         fld = cls.getDeclaredField( "_orb" ) ;
  72                         fld.setAccessible( true ) ;
  73                     } catch (Exception exc) {
  74                         // XXX log exception at FINE
  75                     }
  76                     return fld ;
  77                 }
  78             }
  79         ) ;
  80     }
  81 
  82     public JNDIStateFactoryImpl()
  83     {
  84     }
  85 
  86     /**
  87      * Returns the CORBA object for a Remote object.
  88      * If input is not a Remote object, or if Remote object uses JRMP, return null.
  89      * If the RMI-IIOP library is not available, throw ConfigurationException.
  90      *
  91      * @param orig The object to turn into a CORBA object. If not Remote,
  92      *             or if is a JRMP stub or impl, return null.
  93      * @param name Ignored
  94      * @param ctx The non-null CNCtx whose ORB to use.
  95      * @param env Ignored
  96      * @return The CORBA object for <tt>orig</tt> or null.
  97      * @exception ConfigurationException If the CORBA object cannot be obtained
  98      *    due to configuration problems
  99      * @exception NamingException If some other problem prevented a CORBA
 100      *    object from being obtained from the Remote object.
 101      */
 102     public Object getStateToBind(Object orig, Name name, Context ctx,
 103         Hashtable<?,?> env) throws NamingException
 104     {
 105         if (orig instanceof org.omg.CORBA.Object)
 106             return orig ;
 107 
 108         if (!(orig instanceof Remote))
 109             // Not for this StateFactory
 110             return null ;
 111 
 112         ORB orb = getORB( ctx ) ;
 113         if (orb == null)
 114             // Wrong kind of context, so just give up and let another StateFactory
 115             // try to satisfy getStateToBind.
 116             return null ;
 117 
 118         Remote stub = null;
 119 
 120         try {
 121             stub = PortableRemoteObject.toStub( (Remote)orig ) ;
 122         } catch (Exception exc) {
 123             // XXX log at FINE level?
 124             // Wrong sort of object: just return null to allow another StateFactory
 125             // to handle this.  This can happen easily because this StateFactory
 126             // is specified for the application, not the service context provider.
 127             return null ;
 128         }
 129 
 130         if (StubAdapter.isStub( stub )) {
 131             try {
 132                 StubAdapter.connect( stub, orb ) ;
 133             } catch (Exception exc) {
 134                 if (!(exc instanceof java.rmi.RemoteException)) {
 135                     // XXX log at FINE level?
 136                     // Wrong sort of object: just return null to allow another StateFactory
 137                     // to handle this call.
 138                     return null ;
 139                 }
 140 
 141                 // ignore RemoteException because stub might have already
 142                 // been connected
 143             }
 144         }
 145 
 146         return stub ;
 147     }
 148 
 149     // This is necessary because the _orb field is package private in
 150     // com.sun.jndi.cosnaming.CNCtx.  This is not an ideal solution.
 151     // The best solution for our ORB is to change the CosNaming provider
 152     // to use the StubAdapter.  But this has problems as well, because
 153     // other vendors may use the CosNaming provider with a different ORB
 154     // entirely.
 155     private ORB getORB( Context ctx )
 156     {
 157         ORB orb = null ;
 158 
 159         try {
 160             orb = (ORB)orbField.get( ctx ) ;
 161         } catch (Exception exc) {
 162             // XXX log this exception at FINE level
 163             // ignore the exception and return null.
 164             // Note that the exception may be because ctx
 165             // is not a CosNaming context.
 166         }
 167 
 168         return orb ;
 169     }
 170 }