blob: 81533aa54148896411be45dc97acfa8f1fa44390 [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;
/*
* $RCSfile: REMArrayBeanProxy.java,v $
* $Revision: 1.8 $ $Date: 2005/08/24 20:39:07 $
*/
import java.lang.reflect.Array;
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.CommandErrorException;
import org.eclipse.jem.internal.proxy.common.remote.Commands;
import org.eclipse.jem.internal.proxy.common.remote.Commands.ValueObject;
import org.eclipse.jem.internal.proxy.core.*;
/**
* IDE VM version of the Array proxy
*/
public final class REMArrayBeanProxy extends REMBeanProxy implements IArrayBeanProxy {
private int fLength = -1;
REMArrayBeanProxy(REMProxyFactoryRegistry aRegistry, Integer anID, IBeanTypeProxy aType) {
super(aRegistry, anID, aType);
}
/**
* Get the object at the specified index.
*/
public IBeanProxy get(int index) throws ThrowableProxy {
// Format of getter parms is: (Object (array), int (index)).
Object[] parms = new Object[] {this, new Integer(index)};
// If the component type is primitive, we need to use the correct getter so that a valid value is returned,
// if we just used the standard get, if the type was "int" the value returned would be an java.lang.Integer.
IBeanTypeProxy compType = ((IArrayBeanTypeProxy) getTypeProxy()).getComponentType();
if (!compType.isPrimitive()) {
// Use standard getter.
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayGet()).invokeWithParms(null, parms);
} else {
// Use the correct primitive getter.
int id = ((IREMBeanProxy) compType).getID().intValue();
switch (id) {
case Commands.BYTE_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayGetByte()).invokeWithParms(null, parms);
case Commands.BOOLEAN_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayGetBoolean()).invokeWithParms(null, parms);
case Commands.CHARACTER_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayGetChar()).invokeWithParms(null, parms);
case Commands.DOUBLE_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayGetDouble()).invokeWithParms(null, parms);
case Commands.FLOAT_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayGetFloat()).invokeWithParms(null, parms);
case Commands.INTEGER_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayGetInt()).invokeWithParms(null, parms);
case Commands.LONG_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayGetLong()).invokeWithParms(null, parms);
case Commands.SHORT_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayGetShort()).invokeWithParms(null, parms);
}
}
return null;
}
/**
* Get the object at the specified multi-dimensional index.
* The array must be at least the number of dimensions specified,
* and each index along the way must exist.
* The number of dimensions can't be greater than the number
* of dimensions of the real object.
*/
public IBeanProxy get(int [] indexes) throws ThrowableProxy {
// Format of getter parms is: (Object (array), int[] (indexes)).
Object[] parms = new Object[] {this, indexes};
// If the component type at the specified dimension is primitive, we need to use the correct getter so that a valid value is returned,
// if we just used the standard get, if the type was "int" the value returned would be an java.lang.Integer.
int dims = ((IArrayBeanTypeProxy) getTypeProxy()).getDimensions();
if (dims < indexes.length)
throw new IllegalArgumentException(); // Too many dimensions
IBeanTypeProxy finalCompType = ((IArrayBeanTypeProxy) getTypeProxy()).getFinalComponentType();
if (dims == indexes.length && finalCompType.isPrimitive()) {
// Use the correct primitive getter because we are accessing the final component and it is primitive.
int id = ((IREMBeanProxy) finalCompType).getID().intValue();
switch (id) {
case Commands.BYTE_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayHelperGetByte()).invokeWithParms(null, parms);
case Commands.BOOLEAN_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayHelperGetBoolean()).invokeWithParms(null, parms);
case Commands.CHARACTER_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayHelperGetChar()).invokeWithParms(null, parms);
case Commands.DOUBLE_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayHelperGetDouble()).invokeWithParms(null, parms);
case Commands.FLOAT_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayHelperGetFloat()).invokeWithParms(null, parms);
case Commands.INTEGER_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayHelperGetInt()).invokeWithParms(null, parms);
case Commands.LONG_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayHelperGetLong()).invokeWithParms(null, parms);
case Commands.SHORT_TYPE:
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayHelperGetShort()).invokeWithParms(null, parms);
}
} else {
// It is not the final component, or it is not primitive, use the standard accessor.
return ((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayHelperGet()).invokeWithParms(null, parms);
}
return null;
}
/**
* Set the object at the specified index.
*/
public void set(IBeanProxy value, int index) throws ThrowableProxy {
// Format of setter parms is: (Object (array), int (index), Object (value)).
Object[] parms = new Object[] {this, new Integer(index), value};
((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArraySet()).invokeWithParms(null, parms);
}
/**
* Set the object at the specified multi-dimensional index.
* The array must be at least the number of dimensions specified,
* and each index along the way must exist.
* The number of dimensions can't be greater than the number
* of dimensions of the real object.
*/
public void set(IBeanProxy value, int [] indexes) throws ThrowableProxy {
// Format of setter parms is: (Object (array), int[] (indexes), Object (value)).
Object[] parms = new Object[] {this, indexes, value};
((IREMMethodProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayHelperSet()).invokeWithParms(null, parms);
}
/**
* Get the length of the first dimension of this array.
* If there are multi-dimensions, you must get the appropriate
* dimension from the get method to see the size of that dimension.
*
* e.g.
* int [3] returns 3
* int [3][2] returns 3
*
* ((IArrayBeanProxy) get(1)).getLength() returns 2
* Since arrays do not have to be homogenous, there could
* be a different length array for each of the arrays
* returned from the first dimension, the returned length
* from get(2) and get(3) could result in a different value
* from get(1).
*/
public int getLength() {
if (fLength == -1) {
// It hasn't yet been quiered.
fLength = ((IIntegerBeanProxy) REMStandardBeanProxyConstants.getConstants(fFactory).getArrayGetLength().invokeCatchThrowableExceptions(null, this)).intValue();
}
return fLength;
}
public IBeanProxy getCatchThrowableException(int index){
try {
return get(index);
} 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;
}
}
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IArrayBeanProxy#getSnapshot()
*/
public IBeanProxy[] getSnapshot() throws ThrowableProxy {
IREMConnection connect = fFactory.getFreeConnection();
REMStandardBeanProxyFactory proxyFactory = (REMStandardBeanProxyFactory) fFactory.getBeanProxyFactory();
proxyFactory.startTransaction(); // This is definately a transaction, so start it.
try {
Commands.ValueObject returnValue = new Commands.ValueObject();
try {
try {
connect.getArrayContents(getID().intValue(), returnValue);
return processReturnValue(connect, returnValue);
} catch (CommandErrorException e) {
proxyFactory.processErrorReturn(e);
}
} catch (CommandException e) {
if (!e.isRecoverable()) {
// Close the connection and try again.
fFactory.closeConnection(connect);
connect = null;
connect = fFactory.getFreeConnection();
try {
connect.getArrayContents(getID().intValue(), returnValue);
return processReturnValue(connect, 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);
}
return null;
}
/*
* @param returnValue
* @return
*
* @since 1.1.0
*/
private IBeanProxy[] processReturnValue(IREMConnection connection, ValueObject returnValue) throws CommandException, ThrowableProxy {
// It is an array containing IDs, as it normally would be.
// However it will become IBeanProxy[]. That is because if ID's
// they must be proxies over here.
BeanProxyValueSender valueSender = new BeanProxyValueSender((REMStandardBeanProxyFactory) fFactory.getBeanProxyFactory(), returnValue);
connection.readProxyArrayValues(returnValue, valueSender, false);
Exception e = valueSender.getException();
if (e != null) {
if (e instanceof ThrowableProxy)
throw (ThrowableProxy) e;
else
throw (CommandException) e;
}
Object vals = valueSender.getArray();
IBeanProxy[] proxyArray = new IBeanProxy[Array.getLength(vals)];
System.arraycopy(vals, 0, proxyArray, 0, proxyArray.length);
return proxyArray;
}
}