1 /*
   2  * Copyright (c) 2003, 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.util.Map ;
  29 import java.util.HashMap ;
  30 import java.util.Set ;
  31 import java.util.HashSet ;
  32 import java.util.List ;
  33 import java.util.ArrayList ;
  34 import java.util.Iterator ;
  35 
  36 import java.lang.reflect.Method ;
  37 
  38 import java.rmi.Remote ;
  39 
  40 import javax.rmi.CORBA.Tie ;
  41 
  42 import com.sun.corba.se.spi.orbutil.proxy.InvocationHandlerFactory ;
  43 
  44 import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator ;
  45 import com.sun.corba.se.spi.presentation.rmi.DynamicMethodMarshaller ;
  46 import com.sun.corba.se.spi.presentation.rmi.PresentationManager ;
  47 
  48 import com.sun.corba.se.spi.logging.CORBALogDomains ;
  49 
  50 import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
  51 
  52 import com.sun.corba.se.impl.presentation.rmi.IDLNameTranslatorImpl ;
  53 import com.sun.corba.se.impl.presentation.rmi.StubFactoryProxyImpl ;
  54 
  55 import com.sun.corba.se.impl.orbutil.graph.Node ;
  56 import com.sun.corba.se.impl.orbutil.graph.Graph ;
  57 import com.sun.corba.se.impl.orbutil.graph.GraphImpl ;
  58 
  59 public final class PresentationManagerImpl implements PresentationManager
  60 {
  61     private Map classToClassData ;
  62     private Map methodToDMM ;
  63     private PresentationManager.StubFactoryFactory staticStubFactoryFactory ;
  64     private PresentationManager.StubFactoryFactory dynamicStubFactoryFactory ;
  65     private ORBUtilSystemException wrapper = null ;
  66     private boolean useDynamicStubs ;
  67 
  68     public PresentationManagerImpl( boolean useDynamicStubs )
  69     {
  70         this.useDynamicStubs = useDynamicStubs ;
  71         wrapper = ORBUtilSystemException.get(
  72             CORBALogDomains.RPC_PRESENTATION ) ;
  73 
  74         // XXX these should probably be WeakHashMaps.
  75         classToClassData = new HashMap() ;
  76         methodToDMM = new HashMap() ;
  77     }
  78 
  79 ////////////////////////////////////////////////////////////////////////////////
  80 // PresentationManager interface
  81 ////////////////////////////////////////////////////////////////////////////////
  82 
  83     public synchronized DynamicMethodMarshaller getDynamicMethodMarshaller(
  84         Method method )
  85     {
  86         if (method == null)
  87             return null ;
  88 
  89         DynamicMethodMarshaller result =
  90             (DynamicMethodMarshaller)methodToDMM.get( method ) ;
  91         if (result == null) {
  92             result = new DynamicMethodMarshallerImpl( method ) ;
  93             methodToDMM.put( method, result ) ;
  94         }
  95 
  96         return result ;
  97     }
  98 
  99     public synchronized ClassData getClassData( Class cls )
 100     {
 101         ClassData result = (ClassData)classToClassData.get( cls ) ;
 102         if (result == null) {
 103             result = new ClassDataImpl( cls ) ;
 104             classToClassData.put( cls, result ) ;
 105         }
 106 
 107         return result ;
 108     }
 109 
 110     private class ClassDataImpl implements PresentationManager.ClassData
 111     {
 112         private Class cls ;
 113         private IDLNameTranslator nameTranslator ;
 114         private String[] typeIds ;
 115         private PresentationManager.StubFactory sfactory ;
 116         private InvocationHandlerFactory ihfactory ;
 117         private Map dictionary ;
 118 
 119         public ClassDataImpl( Class cls )
 120         {
 121             this.cls = cls ;
 122             Graph gr = new GraphImpl() ;
 123             NodeImpl root = new NodeImpl( cls ) ;
 124             Set rootSet = getRootSet( cls, root, gr ) ;
 125 
 126             // At this point, rootSet contains those remote interfaces
 127             // that are not related by inheritance, and gr contains
 128             // all reachable remote interfaces.
 129 
 130             Class[] interfaces = getInterfaces( rootSet ) ;
 131             nameTranslator = IDLNameTranslatorImpl.get( interfaces ) ;
 132             typeIds = makeTypeIds( root, gr, rootSet ) ;
 133             ihfactory = new InvocationHandlerFactoryImpl(
 134                 PresentationManagerImpl.this, this ) ;
 135             dictionary = new HashMap() ;
 136         }
 137 
 138         public Class getMyClass()
 139         {
 140             return cls ;
 141         }
 142 
 143         public IDLNameTranslator getIDLNameTranslator()
 144         {
 145             return nameTranslator ;
 146         }
 147 
 148         public String[] getTypeIds()
 149         {
 150             return typeIds ;
 151         }
 152 
 153         public InvocationHandlerFactory getInvocationHandlerFactory()
 154         {
 155             return ihfactory ;
 156         }
 157 
 158         public Map getDictionary()
 159         {
 160             return dictionary ;
 161         }
 162     }
 163 
 164     public PresentationManager.StubFactoryFactory getStubFactoryFactory(
 165         boolean isDynamic )
 166     {
 167         if (isDynamic)
 168             return dynamicStubFactoryFactory ;
 169         else
 170             return staticStubFactoryFactory ;
 171     }
 172 
 173     public void setStubFactoryFactory( boolean isDynamic,
 174         PresentationManager.StubFactoryFactory sff )
 175     {
 176         if (isDynamic)
 177             dynamicStubFactoryFactory = sff ;
 178         else
 179             staticStubFactoryFactory = sff ;
 180     }
 181 
 182     public Tie getTie()
 183     {
 184         return dynamicStubFactoryFactory.getTie( null ) ;
 185     }
 186 
 187     public boolean useDynamicStubs()
 188     {
 189         return useDynamicStubs ;
 190     }
 191 
 192 ////////////////////////////////////////////////////////////////////////////////
 193 // Graph computations
 194 ////////////////////////////////////////////////////////////////////////////////
 195 
 196     private Set getRootSet( Class target, NodeImpl root, Graph gr )
 197     {
 198         Set rootSet = null ;
 199 
 200         if (target.isInterface()) {
 201             gr.add( root ) ;
 202             rootSet = gr.getRoots() ; // rootSet just contains root here
 203         } else {
 204             // Use this class and its superclasses (not Object) as initial roots
 205             Class superclass = target ;
 206             Set initialRootSet = new HashSet() ;
 207             while ((superclass != null) && !superclass.equals( Object.class )) {
 208                 Node node = new NodeImpl( superclass ) ;
 209                 gr.add( node ) ;
 210                 initialRootSet.add( node ) ;
 211                 superclass = superclass.getSuperclass() ;
 212             }
 213 
 214             // Expand all nodes into the graph
 215             gr.getRoots() ;
 216 
 217             // remove the roots and find roots again
 218             gr.removeAll( initialRootSet ) ;
 219             rootSet = gr.getRoots() ;
 220         }
 221 
 222         return rootSet ;
 223     }
 224 
 225     private Class[] getInterfaces( Set roots )
 226     {
 227         Class[] classes = new Class[ roots.size() ] ;
 228         Iterator iter = roots.iterator() ;
 229         int ctr = 0 ;
 230         while (iter.hasNext()) {
 231             NodeImpl node = (NodeImpl)iter.next() ;
 232             classes[ctr++] = node.getInterface() ;
 233         }
 234 
 235         return classes ;
 236     }
 237 
 238     private String[] makeTypeIds( NodeImpl root, Graph gr, Set rootSet )
 239     {
 240         Set nonRootSet = new HashSet( gr ) ;
 241         nonRootSet.removeAll( rootSet ) ;
 242 
 243         // List<String> for the typeids
 244         List result = new ArrayList() ;
 245 
 246         if (rootSet.size() > 1) {
 247             // If the rootSet has more than one element, we must
 248             // put the type id of the implementation class first.
 249             // Root represents the implementation class here.
 250             result.add( root.getTypeId() ) ;
 251         }
 252 
 253         addNodes( result, rootSet ) ;
 254         addNodes( result, nonRootSet ) ;
 255 
 256         return (String[])result.toArray( new String[result.size()] ) ;
 257     }
 258 
 259     private void addNodes( List resultList, Set nodeSet )
 260     {
 261         Iterator iter = nodeSet.iterator() ;
 262         while (iter.hasNext()) {
 263             NodeImpl node = (NodeImpl)iter.next() ;
 264             String typeId = node.getTypeId() ;
 265             resultList.add( typeId ) ;
 266         }
 267     }
 268 
 269     private static class NodeImpl implements Node
 270     {
 271         private Class interf ;
 272 
 273         public Class getInterface()
 274         {
 275             return interf ;
 276         }
 277 
 278         public NodeImpl( Class interf )
 279         {
 280             this.interf = interf ;
 281         }
 282 
 283         public String getTypeId()
 284         {
 285             return "RMI:" + interf.getName() + ":0000000000000000" ;
 286         }
 287 
 288         public Set getChildren()
 289         {
 290             Set result = new HashSet() ;
 291             Class[] interfaces = interf.getInterfaces() ;
 292             for (int ctr=0; ctr<interfaces.length; ctr++) {
 293                 Class cls = interfaces[ctr] ;
 294                 if (Remote.class.isAssignableFrom(cls) &&
 295                     !Remote.class.equals(cls))
 296                     result.add( new NodeImpl( cls ) ) ;
 297             }
 298 
 299             return result ;
 300         }
 301 
 302         public String toString()
 303         {
 304             return "NodeImpl[" + interf + "]" ;
 305         }
 306 
 307         public int hashCode()
 308         {
 309             return interf.hashCode() ;
 310         }
 311 
 312         public boolean equals( Object obj )
 313         {
 314             if (this == obj)
 315                 return true ;
 316 
 317             if (!(obj instanceof NodeImpl))
 318                 return false ;
 319 
 320             NodeImpl other = (NodeImpl)obj ;
 321 
 322             return other.interf.equals( interf ) ;
 323         }
 324     }
 325 }