/*
* Copyright (c) 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.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import org.jboss.com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandler;
import org.jboss.com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl;
import org.jboss.com.sun.corba.se.spi.orbutil.proxy.DelegateInvocationHandlerImpl;
import org.jboss.com.sun.corba.se.spi.orbutil.proxy.InvocationHandlerFactory;
import org.jboss.com.sun.corba.se.spi.orbutil.proxy.LinkedInvocationHandler;
import org.jboss.com.sun.corba.se.spi.presentation.rmi.DynamicStub;
import org.jboss.com.sun.corba.se.spi.presentation.rmi.PresentationManager;
public class InvocationHandlerFactoryImpl implements InvocationHandlerFactory
{
private final PresentationManager.ClassData classData;
private final PresentationManager pm;
private Class<?>[] proxyInterfaces;
public InvocationHandlerFactoryImpl(PresentationManager pm, PresentationManager.ClassData classData)
{
this.classData = classData;
this.pm = pm;
Class<?>[] remoteInterfaces = classData.getIDLNameTranslator().getInterfaces();
proxyInterfaces = new Class[remoteInterfaces.length + 1];
for (int ctr = 0; ctr < remoteInterfaces.length; ctr++)
proxyInterfaces[ctr] = remoteInterfaces[ctr];
proxyInterfaces[remoteInterfaces.length] = DynamicStub.class;
}
private class CustomCompositeInvocationHandlerImpl extends CompositeInvocationHandlerImpl
implements
LinkedInvocationHandler,
Serializable
{
private transient DynamicStub stub;
public void setProxy(Proxy proxy)
{
((DynamicStubImpl) stub).setSelf((DynamicStub) proxy);
}
public Proxy getProxy()
{
return (Proxy) ((DynamicStubImpl) stub).getSelf();
}
public CustomCompositeInvocationHandlerImpl(DynamicStub stub)
{
this.stub = stub;
}
/**
* Return the stub, which will actually be written to the stream. It will be custom marshalled, with the actual
* writing done in StubIORImpl. There is a corresponding readResolve method on DynamicStubImpl which will
* re-create the full invocation handler on read, and return the invocation handler on the readResolve method.
*/
public Object writeReplace() throws ObjectStreamException
{
return stub;
}
}
public InvocationHandler getInvocationHandler()
{
final DynamicStub stub = new DynamicStubImpl(classData.getTypeIds());
return getInvocationHandler(stub);
}
// This is also used in DynamicStubImpl to implement readResolve.
InvocationHandler getInvocationHandler(DynamicStub stub)
{
// Create an invocation handler for the methods defined on DynamicStub, which extends org.omg.CORBA.Object. This
// handler delegates all calls directly to a DynamicStubImpl, which extends org.omg.CORBA.portable.ObjectImpl.
InvocationHandler dynamicStubHandler = DelegateInvocationHandlerImpl.create(stub);
// Create an invocation handler that handles any remote interface methods.
InvocationHandler stubMethodHandler = new StubInvocationHandlerImpl(pm, classData, stub);
// Create a composite handler that handles the DynamicStub interface as well as the remote interfaces.
final CompositeInvocationHandler handler = new CustomCompositeInvocationHandlerImpl(stub);
handler.addInvocationHandler(DynamicStub.class, dynamicStubHandler);
handler.addInvocationHandler(org.omg.CORBA.Object.class, dynamicStubHandler);
handler.addInvocationHandler(Object.class, dynamicStubHandler);
// If the method passed to invoke is not from DynamicStub or its superclasses, it must be from an implemented
// interface, so we just handle all of these with the stubMethodHandler. This used to be done be adding explicit
// entries for stubMethodHandler for each remote interface, but that does not work correctly for abstract
// interfaces, since the graph analysis ignores abstract interfaces in order to compute the type ids correctly
// (see PresentationManagerImpl.NodeImpl.getChildren). Rather than produce more graph traversal code to handle
// this problem, we simply use a default. This also points to a possible optimization: just use explicit checks
// for the three special classes, rather than a general table lookup that usually fails.
handler.setDefaultHandler(stubMethodHandler);
return handler;
}
public Class<?>[] getProxyInterfaces()
{
return proxyInterfaces;
}
}