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 
PresentationManagerImpl( boolean useDynamicStubs )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 
getDynamicMethodMarshaller( Method method )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 
getClassData( Class cls )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 
ClassDataImpl( Class cls )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 
getMyClass()138         public Class getMyClass()
139         {
140             return cls ;
141         }
142 
getIDLNameTranslator()143         public IDLNameTranslator getIDLNameTranslator()
144         {
145             return nameTranslator ;
146         }
147 
getTypeIds()148         public String[] getTypeIds()
149         {
150             return typeIds ;
151         }
152 
getInvocationHandlerFactory()153         public InvocationHandlerFactory getInvocationHandlerFactory()
154         {
155             return ihfactory ;
156         }
157 
getDictionary()158         public Map getDictionary()
159         {
160             return dictionary ;
161         }
162     }
163 
getStubFactoryFactory( boolean isDynamic )164     public PresentationManager.StubFactoryFactory getStubFactoryFactory(
165         boolean isDynamic )
166     {
167         if (isDynamic)
168             return dynamicStubFactoryFactory ;
169         else
170             return staticStubFactoryFactory ;
171     }
172 
setStubFactoryFactory( boolean isDynamic, PresentationManager.StubFactoryFactory sff )173     public void setStubFactoryFactory( boolean isDynamic,
174         PresentationManager.StubFactoryFactory sff )
175     {
176         if (isDynamic)
177             dynamicStubFactoryFactory = sff ;
178         else
179             staticStubFactoryFactory = sff ;
180     }
181 
getTie()182     public Tie getTie()
183     {
184         return dynamicStubFactoryFactory.getTie( null ) ;
185     }
186 
useDynamicStubs()187     public boolean useDynamicStubs()
188     {
189         return useDynamicStubs ;
190     }
191 
192 ////////////////////////////////////////////////////////////////////////////////
193 // Graph computations
194 ////////////////////////////////////////////////////////////////////////////////
195 
getRootSet( Class target, NodeImpl root, Graph gr )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 
getInterfaces( Set roots )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 
makeTypeIds( NodeImpl root, Graph gr, Set rootSet )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 
addNodes( List resultList, Set nodeSet )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 
getInterface()273         public Class getInterface()
274         {
275             return interf ;
276         }
277 
NodeImpl( Class interf )278         public NodeImpl( Class interf )
279         {
280             this.interf = interf ;
281         }
282 
getTypeId()283         public String getTypeId()
284         {
285             return "RMI:" + interf.getName() + ":0000000000000000" ;
286         }
287 
getChildren()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 
toString()302         public String toString()
303         {
304             return "NodeImpl[" + interf + "]" ;
305         }
306 
hashCode()307         public int hashCode()
308         {
309             return interf.hashCode() ;
310         }
311 
equals( Object obj )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 }
326