PresentationManagerImpl.java revision 608:7e06bf1dcb09
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
26package com.sun.corba.se.impl.presentation.rmi ;
27
28import java.util.Map ;
29import java.util.HashMap ;
30import java.util.Set ;
31import java.util.HashSet ;
32import java.util.List ;
33import java.util.ArrayList ;
34import java.util.Iterator ;
35
36import java.lang.reflect.Method ;
37
38import java.rmi.Remote ;
39
40import javax.rmi.CORBA.Tie ;
41
42import com.sun.corba.se.spi.orbutil.proxy.InvocationHandlerFactory ;
43
44import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator ;
45import com.sun.corba.se.spi.presentation.rmi.DynamicMethodMarshaller ;
46import com.sun.corba.se.spi.presentation.rmi.PresentationManager ;
47
48import com.sun.corba.se.spi.logging.CORBALogDomains ;
49
50import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
51
52import com.sun.corba.se.impl.presentation.rmi.IDLNameTranslatorImpl ;
53import com.sun.corba.se.impl.presentation.rmi.StubFactoryProxyImpl ;
54
55import com.sun.corba.se.impl.orbutil.graph.Node ;
56import com.sun.corba.se.impl.orbutil.graph.Graph ;
57import com.sun.corba.se.impl.orbutil.graph.GraphImpl ;
58
59public 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}
326