blob: 681a90d99f9a283162416b676eb4c7fa1a80776a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jem.internal.proxy.remote;
/*
*/
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jem.internal.proxy.common.CommandException;
import org.eclipse.jem.internal.proxy.common.remote.*;
import org.eclipse.jem.internal.proxy.core.*;
/**
* Remote VM implementation of the MethodProxy
*/
final class REMMethodProxy extends REMAccessibleObjectProxy implements IREMMethodProxy {
private IBeanTypeProxy fDeclaringType;
private String fMethodName;
private IBeanTypeProxy[] fParameterTypes;
private IBeanTypeProxy fReturnType;
REMMethodProxy(REMProxyFactoryRegistry aRegistry, Integer anID) {
super(aRegistry, anID);
}
public IBeanTypeProxy getClassType() {
if (fDeclaringType == null)
fDeclaringType =
(IBeanTypeProxy) REMStandardBeanProxyConstants
.getConstants(fFactory)
.getMethodDeclaringClassMessage()
.invokeCatchThrowableExceptions(
this);
return fDeclaringType;
}
public String getName() {
if (fMethodName == null) {
IStringBeanProxy proxy =
(IStringBeanProxy) REMStandardBeanProxyConstants
.getConstants(fFactory)
.getMethodMethodNameMessage()
.invokeCatchThrowableExceptions(
this);
if (proxy != null)
fMethodName = proxy.stringValue();
else
fMethodName = ""; //$NON-NLS-1$
}
return fMethodName;
}
public synchronized IBeanTypeProxy[] getParameterTypes() {
if (fParameterTypes == null) {
IArrayBeanProxy parmTypes = (IArrayBeanProxy) REMStandardBeanProxyConstants.getConstants(fFactory)
.getMethodParameterTypesMessage().invokeCatchThrowableExceptions(this);
if (parmTypes == null)
fParameterTypes = new IBeanTypeProxy[0]; // There was some error, only way null is returned
else {
int len = parmTypes.getLength();
fParameterTypes = new IBeanTypeProxy[len];
for (int i = 0; i < len; i++)
try {
fParameterTypes[i] = (IBeanTypeProxy) parmTypes.get(i);
} catch (ThrowableProxy e) {
}
fFactory.releaseProxy(parmTypes); // Don't need the array on the server anymore.
}
}
return fParameterTypes;
}
public IBeanTypeProxy getReturnType() {
if (fReturnType == null)
fReturnType =
(IBeanTypeProxy) REMStandardBeanProxyConstants
.getConstants(fFactory)
.getMethodReturnTypeMessage()
.invokeCatchThrowableExceptions(
this);
return fReturnType;
}
public IBeanProxy invoke(IBeanProxy subject) throws ThrowableProxy {
return invoke(subject, (IBeanProxy[]) null);
}
public IBeanProxy invoke(IBeanProxy subject, IBeanProxy[] parms) throws ThrowableProxy {
return invokeWithParms(subject, parms);
}
/**
* The internal method that allows mixture of constants (e.g. String) with bean proxies.
* A parm value can be a REMMethodProxy.ParmArray. This means this parm is an array that
* needs to have a ValueRetriever created for it. This is used if the array has ID's in
* it and is not an existing array on the server or all constant values.
*
* NOTE: It is assumed that all IBeanTypeProxies of the parms have already been retrieved.
* It should still work, but it could be asking for them in the middle of the request
* if they are not first gotton.
*
* NOTE: This is in IREMMethodProxy only so that other REM proxy implementations can access it.
*/
public IBeanProxy invokeWithParms(IBeanProxy subject, final Object[] parms) throws ThrowableProxy {
IREMConnection connect = fFactory.getFreeConnection();
REMStandardBeanProxyFactory proxyFactory = (REMStandardBeanProxyFactory) fFactory.getBeanProxyFactory();
proxyFactory.startTransaction(); // This is definately a transaction, so start it.
try {
Commands.ValueObject subjectValue = new Commands.ValueObject();
if (subject != null)
((IREMBeanProxy) subject).renderBean(subjectValue);
Commands.ValueObject parmsValue = new Commands.ValueObject();
class Retriever implements Commands.ValueRetrieve {
int index = 0;
Object[] array;
Commands.ValueObject worker = new Commands.ValueObject();
IStandardBeanTypeProxyFactory typeFactory = fFactory.getBeanTypeProxyFactory();
public Retriever(Object[] anArray) {
array = anArray;
}
public void reset() {
index = 0;
}
public Commands.ValueObject nextValue() {
Object parm = array[index++];
if (parm != null)
if (parm instanceof IREMBeanProxy)
((IREMBeanProxy) parm).renderBean(worker);
else if (parm instanceof TransmitableArray) {
// It is another array, create a new retriever.
worker.setArrayIDS(
new Retriever(((TransmitableArray) parm).array),
((TransmitableArray) parm).array.length,
((TransmitableArray) parm).componentTypeID);
} else {
// It's an object. Need to get bean type so that we can send it.
IREMBeanProxy type = (IREMBeanProxy) typeFactory.getBeanTypeProxy(parm.getClass().getName());
if (type == null)
throw new IllegalArgumentException();
int classID = type.getID().intValue();
worker.setAsObject(parm, classID);
}
else
worker.set();
return worker;
}
};
Retriever retriever = null;
if (parms != null) {
// Have a local definition of the retriever so that the retriever can create
// another one of itself if necessary.
parmsValue.setArrayIDS(retriever = new Retriever(parms), parms.length, Commands.OBJECT_CLASS); // Create Object[].
}
Commands.ValueObject returnValue = new Commands.ValueObject();
try {
invoke(connect, proxyFactory, subjectValue, parmsValue, returnValue);
return proxyFactory.getBeanProxy(returnValue);
} catch (CommandException e) {
if (!e.isRecoverable()) {
// Close the connection and try again.
fFactory.closeConnection(connect);
connect = null;
connect = fFactory.getFreeConnection();
try {
if (retriever != null)
retriever.reset();
invoke(connect, proxyFactory, subjectValue, parmsValue, returnValue);
return proxyFactory.getBeanProxy(returnValue);
} catch (CommandException eAgain) {
// Failed again. Just close and print trace.
fFactory.closeConnection(connect);
connect = null;
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", eAgain)); //$NON-NLS-1$
return null;
}
} else {
// A recoverable error, print trace and return
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$
return null;
}
}
} finally {
proxyFactory.stopTransaction();
if (connect != null)
fFactory.returnConnection(connect);
}
}
private void invoke(
IREMConnection connect,
REMStandardBeanProxyFactory proxyFactory,
Commands.ValueObject subjectValue,
Commands.ValueObject parmsValue,
Commands.ValueObject returnValue)
throws ThrowableProxy, CommandException {
try {
connect.invokeMethod(getID().intValue(), subjectValue, parmsValue, returnValue);
} catch (CommandErrorException e) {
proxyFactory.processErrorReturn(e);
}
}
public IBeanProxy invoke(IBeanProxy subject, IBeanProxy parm) throws ThrowableProxy {
return invoke(subject, new IBeanProxy[] { parm });
}
public IBeanProxy invokeCatchThrowableExceptions(IBeanProxy subject) {
try {
return invoke(subject);
} catch (ThrowableProxy e) {
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$
fFactory.releaseProxy(e); // Since it's no longer needed, get rid of now instead of GC time.
return null;
}
}
public IBeanProxy invokeCatchThrowableExceptions(IBeanProxy subject, IBeanProxy[] parms) {
try {
return invoke(subject, parms);
} catch (ThrowableProxy e) {
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$
fFactory.releaseProxy(e); // Since it's no longer needed, get rid of now instead of GC time.
return null;
}
}
public IBeanProxy invokeCatchThrowableExceptions(IBeanProxy subject, IBeanProxy parm) {
try {
return invoke(subject, parm);
} catch (ThrowableProxy e) {
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$
fFactory.releaseProxy(e); // Since it's no longer needed, get rid of now instead of GC time.
return null;
}
}
/**
* The type proxy is constant proxy out of the method factory.
*/
public IBeanTypeProxy getTypeProxy() {
return ((REMMethodProxyFactory) fFactory.getMethodProxyFactory()).methodType;
}
/**
* The bean is being released, clear out the fields so they can be GC'd if necessary.
* Usually only big objects and proxy fields need to be cleared.
*/
public void release() {
fDeclaringType = null;
fParameterTypes = null;
fReturnType = null;
super.release();
}
}