/* * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package org.jboss.com.sun.corba.se.impl.presentation.rmi; import java.lang.reflect.Method; import java.rmi.Remote; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.rmi.CORBA.Tie; import org.jboss.com.sun.corba.se.impl.orbutil.graph.Graph; import org.jboss.com.sun.corba.se.impl.orbutil.graph.GraphImpl; import org.jboss.com.sun.corba.se.impl.orbutil.graph.Node; import org.jboss.com.sun.corba.se.spi.orbutil.proxy.InvocationHandlerFactory; import org.jboss.com.sun.corba.se.spi.presentation.rmi.DynamicMethodMarshaller; import org.jboss.com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator; import org.jboss.com.sun.corba.se.spi.presentation.rmi.PresentationManager; public final class PresentationManagerImpl implements PresentationManager { private Map<Class<?>, ClassData> classToClassData; private Map<Method, DynamicMethodMarshaller> methodToDMM; private PresentationManager.StubFactoryFactory staticStubFactoryFactory; private PresentationManager.StubFactoryFactory dynamicStubFactoryFactory; private boolean useDynamicStubs; public PresentationManagerImpl(boolean useDynamicStubs) { this.useDynamicStubs = useDynamicStubs; // XXX these should probably be WeakHashMaps. classToClassData = new HashMap<Class<?>, ClassData>(); methodToDMM = new HashMap<Method, DynamicMethodMarshaller>(); } // ////////////////////////////////////////////////////////////////////////////// // PresentationManager interface // ////////////////////////////////////////////////////////////////////////////// public synchronized DynamicMethodMarshaller getDynamicMethodMarshaller(Method method) { if (method == null) return null; DynamicMethodMarshaller result = methodToDMM.get(method); if (result == null) { result = new DynamicMethodMarshallerImpl(method); methodToDMM.put(method, result); } return result; } public synchronized ClassData getClassData(Class<?> cls) { ClassData result = classToClassData.get(cls); if (result == null) { result = new ClassDataImpl(cls); classToClassData.put(cls, result); } return result; } private class ClassDataImpl implements PresentationManager.ClassData { private Class<?> cls; private IDLNameTranslator nameTranslator; private String[] typeIds; private InvocationHandlerFactory ihfactory; private Map<Object, Object> dictionary; public ClassDataImpl(Class<?> cls) { this.cls = cls; Graph gr = new GraphImpl(); NodeImpl root = new NodeImpl(cls); Set<Node> rootSet = getRootSet(cls, root, gr); // At this point, rootSet contains those remote interfaces that are not related by inheritance, and gr // contains all reachable remote interfaces. Class<?>[] interfaces = getInterfaces(rootSet); nameTranslator = IDLNameTranslatorImpl.get(interfaces); typeIds = makeTypeIds(root, gr, rootSet); ihfactory = new InvocationHandlerFactoryImpl(PresentationManagerImpl.this, this); dictionary = new HashMap<Object, Object>(); } public Class<?> getMyClass() { return cls; } public IDLNameTranslator getIDLNameTranslator() { return nameTranslator; } public String[] getTypeIds() { return typeIds; } public InvocationHandlerFactory getInvocationHandlerFactory() { return ihfactory; } public Map<Object, Object> getDictionary() { return dictionary; } } public PresentationManager.StubFactoryFactory getStubFactoryFactory(boolean isDynamic) { if (isDynamic) return dynamicStubFactoryFactory; else return staticStubFactoryFactory; } public void setStubFactoryFactory(boolean isDynamic, PresentationManager.StubFactoryFactory sff) { if (isDynamic) dynamicStubFactoryFactory = sff; else staticStubFactoryFactory = sff; } public Tie getTie() { return dynamicStubFactoryFactory.getTie(null); } public boolean useDynamicStubs() { return useDynamicStubs; } // ////////////////////////////////////////////////////////////////////////////// // Graph computations // ////////////////////////////////////////////////////////////////////////////// private Set<Node> getRootSet(Class<?> target, NodeImpl root, Graph gr) { Set<Node> rootSet = null; if (target.isInterface()) { gr.add(root); rootSet = gr.getRoots(); // rootSet just contains root here } else { // Use this class and its superclasses (not Object) as initial roots Class<?> superclass = target; Set<Node> initialRootSet = new HashSet<Node>(); while ((superclass != null) && !superclass.equals(Object.class)) { Node node = new NodeImpl(superclass); gr.add(node); initialRootSet.add(node); superclass = superclass.getSuperclass(); } // Expand all nodes into the graph gr.getRoots(); // remove the roots and find roots again gr.removeAll(initialRootSet); rootSet = gr.getRoots(); } return rootSet; } private Class<?>[] getInterfaces(Set<Node> roots) { Class<?>[] classes = new Class[roots.size()]; Iterator<Node> iter = roots.iterator(); int ctr = 0; while (iter.hasNext()) { NodeImpl node = (NodeImpl) iter.next(); classes[ctr++] = node.getInterface(); } return classes; } private String[] makeTypeIds(NodeImpl root, Graph gr, Set<Node> rootSet) { Set<Node> nonRootSet = new HashSet<Node>(gr); nonRootSet.removeAll(rootSet); // List<String> for the typeids List<String> result = new ArrayList<String>(); if (rootSet.size() > 1) { // If the rootSet has more than one element, we must put the type id of the implementation class first. Root // represents the implementation class here. result.add(root.getTypeId()); } addNodes(result, rootSet); addNodes(result, nonRootSet); return result.toArray(new String[result.size()]); } private void addNodes(List<String> resultList, Set<Node> nodeSet) { Iterator<Node> iter = nodeSet.iterator(); while (iter.hasNext()) { NodeImpl node = (NodeImpl) iter.next(); String typeId = node.getTypeId(); resultList.add(typeId); } } private static class NodeImpl implements Node { private Class<?> interf; public Class<?> getInterface() { return interf; } public NodeImpl(Class<?> interf) { this.interf = interf; } public String getTypeId() { return "RMI:" + interf.getName() + ":0000000000000000"; } public Set<Node> getChildren() { Set<Node> result = new HashSet<Node>(); Class<?>[] interfaces = interf.getInterfaces(); for (int ctr = 0; ctr < interfaces.length; ctr++) { Class<?> cls = interfaces[ctr]; if (Remote.class.isAssignableFrom(cls) && !Remote.class.equals(cls)) result.add(new NodeImpl(cls)); } return result; } public String toString() { return "NodeImpl[" + interf + "]"; } public int hashCode() { return interf.hashCode(); } public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof NodeImpl)) return false; NodeImpl other = (NodeImpl) obj; return other.interf.equals(interf); } } }