blob: 46c9a2365da2e14018c9122996ac6973cb36d05d [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 v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jem.internal.proxy.remote;
/*
*/
import java.text.MessageFormat;
import java.util.*;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jem.internal.proxy.core.*;
import org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyEvent;
import org.eclipse.jem.internal.proxy.common.CommandException;
import org.eclipse.jem.internal.proxy.common.MapTypes;
import org.eclipse.jem.internal.proxy.common.remote.CommandErrorException;
import org.eclipse.jem.internal.proxy.common.remote.Commands;
/**
* We are a beanTypeProxyFactory for creating REMBeanTypeProxy objects Primitive types as well as common types like String are cached for speed of
* lookup. We are the standard one that the VCE uses. Creation date: (12/3/99 2:32:48 PM)
*
* @author: Joe Winchester
*/
public final class REMStandardBeanTypeProxyFactory implements IStandardBeanTypeProxyFactory {
protected final REMProxyFactoryRegistry fFactoryRegistry;
protected REMStandardBeanProxyFactory fBeanFactory;
// Hashtable to cache proxies for classes so they are found on second and subsequent lookups
protected Map fBeanProxies = new HashMap(1000);
// A Cache of bean type proxies that should not ever be released. These are the standard ones
// that we create here. They are never released because they wouldn't be correctly re-created
// if they were. Also they are standard ones with standard ID's that don't change so they
// don't need to be re-created later.
protected Set fPermanentProxies = new HashSet(30);
// Cache of requested but not found bean types. If not maintaining the list, this variable will be null.
// The values are strings (classnames in JNI format).
protected Set fNotFoundTypes = null;
// Cached copy of a few typical bean type proxies.
REMBeanTypeProxy objectClass;
REMClassBeanTypeProxy classClass;
REMVoidBeanTypeProxy voidType;
REMBooleanTypeBeanTypeProxy booleanType;
REMBooleanClassBeanTypeProxy booleanClass;
REMIntegerTypeBeanTypeProxy intType;
REMIntegerClassBeanTypeProxy integerClass;
REMByteTypeBeanTypeProxy byteType;
REMByteClassBeanTypeProxy byteClass;
REMShortClassBeanTypeProxy shortClass;
REMShortTypeBeanTypeProxy shortType;
REMLongClassBeanTypeProxy longClass;
REMLongTypeBeanTypeProxy longType;
REMDoubleClassBeanTypeProxy doubleClass;
REMDoubleTypeBeanTypeProxy doubleType;
REMFloatClassBeanTypeProxy floatClass;
REMFloatTypeBeanTypeProxy floatType;
REMBigDecimalBeanTypeProxy bigDecimalClass;
REMBigIntegerBeanTypeProxy bigIntegerClass;
REMCharacterTypeBeanTypeProxy charType;
REMCharacterClassBeanTypeProxy characterClass;
REMStringBeanTypeProxy stringClass;
/**
* Available to all REM beantypes.
*/
public REMProxyConstants proxyConstants;
/**
* IDEBeanTypeProxyFactory constructor comment.
*/
REMStandardBeanTypeProxyFactory(REMProxyFactoryRegistry aRegistry) {
fFactoryRegistry = aRegistry;
aRegistry.registerBeanTypeProxyFactory(this);
proxyConstants = new REMProxyConstants(aRegistry);
// Now initialize the cache.
objectClass = new REMBeanTypeProxy(fFactoryRegistry, new Integer(Commands.OBJECT_CLASS), Object.class.getName(), null);
classClass = new REMClassBeanTypeProxy(fFactoryRegistry, objectClass);
voidType = new REMVoidBeanTypeProxy(fFactoryRegistry);
booleanType = new REMBooleanTypeBeanTypeProxy(fFactoryRegistry);
booleanClass = new REMBooleanClassBeanTypeProxy(fFactoryRegistry, objectClass);
IBeanTypeProxy numberClass = objectClass.newBeanTypeForClass(new Integer(Commands.NUMBER_CLASS), Number.class.getName(), true);
intType = new REMIntegerTypeBeanTypeProxy(fFactoryRegistry);
integerClass = new REMIntegerClassBeanTypeProxy(fFactoryRegistry, numberClass);
byteType = new REMByteTypeBeanTypeProxy(fFactoryRegistry);
byteClass = new REMByteClassBeanTypeProxy(fFactoryRegistry, numberClass);
shortType = new REMShortTypeBeanTypeProxy(fFactoryRegistry);
shortClass = new REMShortClassBeanTypeProxy(fFactoryRegistry, numberClass);
longType = new REMLongTypeBeanTypeProxy(fFactoryRegistry);
longClass = new REMLongClassBeanTypeProxy(fFactoryRegistry, numberClass);
doubleType = new REMDoubleTypeBeanTypeProxy(fFactoryRegistry);
doubleClass = new REMDoubleClassBeanTypeProxy(fFactoryRegistry, numberClass);
floatType = new REMFloatTypeBeanTypeProxy(fFactoryRegistry);
floatClass = new REMFloatClassBeanTypeProxy(fFactoryRegistry, numberClass);
bigDecimalClass = new REMBigDecimalBeanTypeProxy(fFactoryRegistry, numberClass);
bigIntegerClass = new REMBigIntegerBeanTypeProxy(fFactoryRegistry, numberClass);
charType = new REMCharacterTypeBeanTypeProxy(fFactoryRegistry);
characterClass = new REMCharacterClassBeanTypeProxy(fFactoryRegistry, objectClass);
stringClass = new REMStringBeanTypeProxy(fFactoryRegistry, objectClass);
IBeanTypeProxy throwableClass = new REMThrowableBeanTypeProxy(fFactoryRegistry, new Integer(Commands.THROWABLE_CLASS), Throwable.class
.getName(), objectClass);
IBeanTypeProxy threadClass = objectClass.newBeanTypeForClass(new Integer(Commands.THREAD_CLASS), Thread.class.getName(), false);
IBeanTypeProxy expressionProcessorControllerClass = objectClass.newBeanTypeForClass(new Integer(Commands.EXPRESSIONPROCESSERCONTROLLER_CLASS), "org.eclipse.jem.internal.proxy.vm.remote.ExpressionProcesserController", false); //$NON-NLS-1$
// Initialize the hashtable with the primitives, their lang equivalents, and also common classes like String
// Primitives
fBeanProxies.put(voidType.getTypeName(), voidType);
fBeanProxies.put(intType.getTypeName(), intType);
fBeanProxies.put(booleanType.getTypeName(), booleanType);
fBeanProxies.put(charType.getTypeName(), charType);
fBeanProxies.put(byteType.getTypeName(), byteType);
fBeanProxies.put(shortType.getTypeName(), shortType);
fBeanProxies.put(longType.getTypeName(), longType);
fBeanProxies.put(floatType.getTypeName(), floatType);
fBeanProxies.put(doubleType.getTypeName(), doubleType);
// java.lang primitive peers
// Note that special classes are used for some of these which allow the IDE to get the
// lang objects from the objects that are holding proxies
fBeanProxies.put(integerClass.getTypeName(), integerClass);
fBeanProxies.put(booleanClass.getTypeName(), booleanClass);
fBeanProxies.put(characterClass.getTypeName(), characterClass);
fBeanProxies.put(byteClass.getTypeName(), byteClass);
fBeanProxies.put(shortClass.getTypeName(), shortClass);
fBeanProxies.put(longClass.getTypeName(), longClass);
fBeanProxies.put(floatClass.getTypeName(), floatClass);
fBeanProxies.put(doubleClass.getTypeName(), doubleClass);
fBeanProxies.put(bigDecimalClass.getTypeName(), bigDecimalClass);
fBeanProxies.put(bigIntegerClass.getTypeName(), bigIntegerClass);
fBeanProxies.put(stringClass.getTypeName(), stringClass);
fBeanProxies.put(throwableClass.getTypeName(), throwableClass);
fBeanProxies.put(objectClass.getTypeName(), objectClass);
fBeanProxies.put(classClass.getTypeName(), classClass);
fBeanProxies.put(numberClass.getTypeName(), numberClass);
fBeanProxies.put(threadClass.getTypeName(), threadClass);
fBeanProxies.put(expressionProcessorControllerClass.getTypeName(), expressionProcessorControllerClass);
// Mark these as permanent.
fPermanentProxies.addAll(fBeanProxies.values());
}
/**
* Initialize AFTER BeanProxyFactory has been created. This is REQUIRED! NOTE: It is package protected so that only REMStandardBeanProxyFactory
* can call it when ready.
*/
synchronized void initialize(REMStandardBeanProxyFactory proxyFactory) {
fBeanFactory = proxyFactory;
fBeanFactory.registerProxies(fBeanProxies.values());
}
/*
* This is called when we know we don't have the class registered, so we need to create the proxy. We have a connection passed in and will reuse
* it as necessary
*
* It is important that this be called only from within a transaction.
*/
private synchronized IREMBeanTypeProxy createBeanTypeProxy(String typeName, IREMConnection connection) throws CommandException {
// We don't have the beantype proxy, so create it.
IREMBeanTypeProxy beanTypeProxy = null;
Commands.GetClassReturn ret = null;
try {
ret = getClassReturn(connection, typeName);
} catch (ThrowableProxy ep) {
// Print out the trace and return proxy with init error.
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", ep)); //$NON-NLS-1$
IREMBeanTypeProxy proxy = new REMInitErrorBeanTypeProxy(fFactoryRegistry, MessageFormat.format(ProxyRemoteMessages.ExceptionErrorMsg_EXC_, new Object[] { ep.getTypeProxy().getTypeName(), ep.getProxyLocalizedMessage()}), typeName); //$NON-NLS-1$
registerBeanTypeProxy(proxy, false);
return proxy;
}
if (ret == null) {
if (fNotFoundTypes != null)
fNotFoundTypes.add(typeName);
return null; // The class doesn't even exist on the server.
}
if (typeName.charAt(0) != '[') {
// It is not an array.
IREMBeanTypeProxy superTypeProxy = null;
if (!ret.isInterface && ret.superClassname.length() != 0) {
// Get the beantype proxy of the superclass.
superTypeProxy = getBeanTypeProxy(ret.superClassname, connection);
}
// First check with the factory for the package of the class.
// Inner classes have to use the dollar notation since if they didn't we couldn't tell where
// the package ended and the class started. This check is here in case the
// extension factory can handle this class but needs the id from the server to
// create it.
int packageIndex = typeName.lastIndexOf('.');
if (packageIndex != -1) {
String packageName = typeName.substring(0, packageIndex);
IREMBeanTypeProxyFactory packageFactory = (IREMBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
if (packageFactory != null) {
beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(typeName, new Integer(ret.classID), superTypeProxy);
if (beanTypeProxy != null) {
registerBeanTypeProxy(beanTypeProxy, false);
return beanTypeProxy;
}
}
}
if (ret.isInterface) {
// Interface never have a super type, so we will create a specific type.
beanTypeProxy = new REMInterfaceBeanTypeProxy(fFactoryRegistry, new Integer(ret.classID), typeName);
} else {
// Ask the supertype
// to create a beantype proxy of the same beantype proxy class.
// This is so that any subclasses will get the same beantype proxy class
// for it if it is special.
if (superTypeProxy != null)
beanTypeProxy = superTypeProxy.newBeanTypeForClass(new Integer(ret.classID), typeName, ret.isAbstract);
}
} else
beanTypeProxy = new REMArrayBeanTypeProxy(fFactoryRegistry, new Integer(ret.classID), typeName, objectClass);
// Cache the instance so we can re-use it again
if (beanTypeProxy != null)
registerBeanTypeProxy(beanTypeProxy, false);
return beanTypeProxy;
}
/**
* Using the helper class to find a class by name, then create the proxy.
*/
public IBeanTypeProxy getBeanTypeProxy(String typeName) {
try {
return getBeanTypeProxy(MapTypes.getJNIFormatName(typeName), (IREMConnection) null);
} catch (CommandException e) {
// Try once more (we won't have received recoverable exceptions here, they were already caught and handled)
try {
return getBeanTypeProxy(typeName, (IREMConnection) null);
} catch (CommandException eAgain) {
// Failed again.
ProxyPlugin.getPlugin().getLogger().log(
new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", eAgain)); //$NON-NLS-1$
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#getBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IExpression,
* java.lang.String)
*/
public synchronized IProxyBeanType getBeanTypeProxy(IExpression expression, String typeName) {
typeName = MapTypes.getJNIFormatName(typeName);
// See whether we already have the proxy for the argument name
IProxyBeanType beanTypeProxy = (IProxyBeanType) fBeanProxies.get(typeName);
if (beanTypeProxy != null)
return beanTypeProxy;
// Now see if an expression proxy cached.
beanTypeProxy = ((REMExpression) expression).getBeanType(typeName);
if (beanTypeProxy != null)
return beanTypeProxy;
// If not an array, then see if the package extension mechanism can find it.
// Do this here so that if it is found in the package extension we won't necessarily create an
// extra connection when not needed.
if (typeName.charAt(0) != '[') {
// It is not an array
// First check with the factory for the package of the class.
// Inner classes have to use the dollar notation since if they didn't we couldn't tell where
// the package ended and the class started.
int packageIndex = typeName.lastIndexOf('.');
if (packageIndex != -1) {
String packageName = typeName.substring(0, packageIndex);
IREMBeanTypeProxyFactory packageFactory = (IREMBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
if (packageFactory != null) {
beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(typeName, expression);
if (beanTypeProxy != null) {
registerBeanTypeProxy(beanTypeProxy, false);
return beanTypeProxy;
}
}
}
}
// Need to create the expression proxy for it.
beanTypeProxy = ((Expression) expression).createBeanTypeExpressionProxy(typeName);
registerBeanTypeProxy(beanTypeProxy, false);
return beanTypeProxy;
}
/**
* One that internally allows that we already have a connection to work with. If the connection is null, then one will be created.
*
* It is important that if the connection is not null, then we are in a transaction.
*/
private synchronized IREMBeanTypeProxy getBeanTypeProxy(String typeName, IREMConnection inConnect) throws CommandException {
// See whether we already have the proxy for the argument name
IProxyBeanType beanTypeProxy = (IProxyBeanType) fBeanProxies.get(typeName);
// See if there and resolved, if so, return it. If not resolved, that means we need it NOW
// so we must go for it. When finally resolved the original ExpressionProxy will be deregistered and
// the resolved beantypeproxy will be in its place.
if (beanTypeProxy != null && beanTypeProxy.isBeanProxy()) { return (IREMBeanTypeProxy) beanTypeProxy; }
// If not an array, then see if the package extension mechanism can find it.
// Do this here so that if it is found in the package extension we won't necessarily create an
// extra connection when not needed.
if (typeName.charAt(0) != '[') {
// It is not an array
// First check with the factory for the package of the class.
// Inner classes have to use the dollar notation since if they didn't we couldn't tell where
// the package ended and the class started.
int packageIndex = typeName.lastIndexOf('.');
if (packageIndex != -1) {
String packageName = typeName.substring(0, packageIndex);
IREMBeanTypeProxyFactory packageFactory = (IREMBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
if (packageFactory != null) {
beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(typeName);
if (beanTypeProxy != null) {
registerBeanTypeProxy((IREMBeanTypeProxy) beanTypeProxy, false);
return (IREMBeanTypeProxy) beanTypeProxy;
}
}
}
}
IREMConnection connect = inConnect != null ? inConnect : fFactoryRegistry.getFreeConnection();
if (inConnect == null)
fBeanFactory.startTransaction(); // Start a transation.
try {
return createBeanTypeProxy(typeName, connect);
} catch (CommandException e) {
if (inConnect == null) {
// Need to close the connection, not return it.
fFactoryRegistry.closeConnection(connect);
connect = null; // So that it won't be returned.
}
throw e; // Pass it on up
} finally {
if (inConnect == null)
fBeanFactory.stopTransaction();
if (inConnect == null && connect != null)
fFactoryRegistry.returnConnection(connect);
}
}
/*
* It is important this be called only from within a transaction.
*/
private Commands.GetClassReturn getClassReturn(IREMConnection connection, String className) throws CommandException, ThrowableProxy {
try {
return connection.getClass(className);
} catch (CommandErrorException e) {
fBeanFactory.processErrorReturn(e); // Let proxy factory handle the error return
}
return null;
}
/**
* Return an Array type proxy for the given class name of the specified dimensions. This is a helper method. The same result can be gotton from
* getBeanTypeProxy. e.g. getBeanTypeProxy("java.lang.Object", 3) is the same as: getBeanTypeProxy("[[[Ljava.lang.Object;")
*
* They both result in a type of: Object [][][]
*
* or getBeanTypeProxy("[Ljava.langObject;", 3) becomes Object [][][][]
*/
public IBeanTypeProxy getBeanTypeProxy(String componentClassName, int dimensions) {
return getBeanTypeProxy(getArrayClassName(componentClassName, dimensions));
}
/**
* @param componentClassName
* @param dimensions
* @return
*
* @since 1.1.0
*/
private String getArrayClassName(String componentClassName, int dimensions) {
String jniComponentClassName = MapTypes.getJNIFormatName(componentClassName);
String compType = jniComponentClassName;
if (jniComponentClassName.charAt(0) != '[') {
// We're not already an array, so create correct template.
compType = (String) MapTypes.MAP_TYPENAME_TO_SHORTSIG.get(jniComponentClassName);
if (compType == null) {
// It is a class, and not a type.
compType = "L" + jniComponentClassName + ";"; //$NON-NLS-1$ //$NON-NLS-2$
}
}
// Now create it with the appropriate number of '[' in front.
StringBuffer buffer = new StringBuffer(dimensions + compType.length());
for (int i = 0; i < dimensions; i++)
buffer.append('[');
buffer.append(compType);
return buffer.toString();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#getBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IExpression,
* java.lang.String, int)
*/
public IProxyBeanType getBeanTypeProxy(IExpression expression, String componentClassName, int dimensions) {
return getBeanTypeProxy(expression, getArrayClassName(componentClassName, dimensions));
}
/**
* Get the bean type proxy from a class id. This means that a new class id was sent back from the server that we don't have yet. We need to go ask
* the server for information on this type so that we can create it.
*
* NOTE: This is package protected so that only the standard bean proxy factory can call it.
*
* It is important that this has been called within a transaction.
*/
IREMBeanTypeProxy createBeanTypeProxy(Integer classID) {
IREMConnection connect = fFactoryRegistry.getFreeConnection();
try {
return createBeanTypeProxy(classID, connect);
} catch (CommandException e) {
if (e.isRecoverable()) {
// It is recoverable, print message, keep connection live and return it.
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$
} else {
// Try again, close connection, get a new one.
fFactoryRegistry.closeConnection(connect);
connect = null;
connect = fFactoryRegistry.getFreeConnection();
try {
return createBeanTypeProxy(classID, connect);
} catch (CommandException eAgain) {
// Failed again. Close connection, don't return it.
ProxyPlugin.getPlugin().getLogger().log(
new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", eAgain)); //$NON-NLS-1$
fFactoryRegistry.closeConnection(connect);
connect = null;
}
}
} finally {
if (connect != null)
fFactoryRegistry.returnConnection(connect);
}
return null;
}
/*
* One that internally allows that we already have a connection to work with. If the connection is null, then one will be created.
*
* It is important this be called only from within a transaction.
*/
private synchronized IREMBeanTypeProxy createBeanTypeProxy(Integer classID, IREMConnection connect) throws CommandException {
// We don't have the beantype proxy, so create it.
IREMBeanTypeProxy beanTypeProxy = null;
Commands.GetClassIDReturn ret = null;
try {
ret = getClassIDReturn(connect, classID);
} catch (ThrowableProxy ep) {
// Just print out the trace and return proxy not found.
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", ep)); //$NON-NLS-1$
return null;
}
// If the signature is that of a class.
if (ret.className.charAt(0) != '[') {
// It is not an array.
IREMBeanTypeProxy superTypeProxy = null;
if (!ret.isInterface && ret.superClassname.length() != 0) {
// Get the beantype proxy of the superclass.
superTypeProxy = getBeanTypeProxy(ret.superClassname, connect);
}
// First check with the factory for the package of the class.
// Inner classes have to use the dollar notation since if they didn't we couldn't tell where
// the package ended and the class started.
int packageIndex = ret.className.lastIndexOf('.');
if (packageIndex != -1) {
String packageName = ret.className.substring(0, packageIndex);
IREMBeanTypeProxyFactory packageFactory = (IREMBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
if (packageFactory != null) {
beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(ret.className, classID, superTypeProxy);
if (beanTypeProxy != null) {
registerBeanTypeProxy(beanTypeProxy, false);
return beanTypeProxy;
}
}
}
if (ret.isInterface) {
// Interface never have a super type, so we will let the object class do it for us.
beanTypeProxy = new REMInterfaceBeanTypeProxy(fFactoryRegistry, classID, ret.className);
} else {
// Ask the beantype proxy of the superclass
// to create a beantype proxy of the same beantype proxy class.
// This is so that any subclasses will get the same beantype proxy class
// for it if it is special.
if (superTypeProxy != null)
beanTypeProxy = superTypeProxy.newBeanTypeForClass(classID, ret.className, ret.isAbstract);
}
// Cache the instance so we can re-use it again
if (beanTypeProxy != null)
registerBeanTypeProxy(beanTypeProxy, false);
return beanTypeProxy;
} else {
// It is an array.
beanTypeProxy = new REMArrayBeanTypeProxy(fFactoryRegistry, classID, ret.className, objectClass);
registerBeanTypeProxy(beanTypeProxy, false);
return beanTypeProxy;
}
}
/*
* It is important that this be called only from within a transaction.
*/
private Commands.GetClassIDReturn getClassIDReturn(IREMConnection connection, Integer classID) throws CommandException, ThrowableProxy {
try {
return connection.getClassFromID(classID.intValue());
} catch (CommandErrorException e) {
fBeanFactory.processErrorReturn(e); // Let proxy factory handle the error return
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#registerBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IBeanTypeProxy,
* boolean)
*/
public synchronized void registerBeanTypeProxy(IBeanTypeProxy aBeanTypeProxy, boolean permanent) {
fBeanProxies.put(aBeanTypeProxy.getTypeName(), aBeanTypeProxy);
fBeanFactory.registerProxy((IREMBeanProxy) aBeanTypeProxy);
if (permanent)
fPermanentProxies.add(aBeanTypeProxy);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#registerBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType,
* boolean)
*/
public void registerBeanTypeProxy(IProxyBeanType aProxyBeanType, final boolean permanent) {
if (aProxyBeanType.isBeanProxy())
registerBeanTypeProxy((IBeanTypeProxy) aProxyBeanType, permanent); // A regular kind, do regular registration.
else {
ExpressionProxy beanExpressionProxy = ((ExpressionProxy) aProxyBeanType);
final String typeName = aProxyBeanType.getTypeName();
((REMExpression) beanExpressionProxy.getExpression()).addBeanType(typeName, aProxyBeanType);
beanExpressionProxy.addProxyListener(new ExpressionProxy.ProxyAdapter() {
public void proxyResolved(ProxyEvent event) {
String typeName = ((IProxyBeanType) event.getSource()).getTypeName();
synchronized (REMStandardBeanTypeProxyFactory.this) {
if (!fBeanProxies.containsKey(typeName)) {
// It hasn't been resolved through some other means. So this is good. Actually this should never
// occur because upon resolution we've already registered the bean type proxy through the
// normal mechanisms. But to be safe, we'll do it here.
fBeanProxies.put(typeName, event.getProxy());
if (permanent)
fPermanentProxies.add(event.getProxy());
}
}
}
public void proxyNotResolved(ExpressionProxy.ProxyEvent event) {
((REMExpression) ((ExpressionProxy) event.getSource()).getExpression()).removeBeanType(typeName);
}
});
}
}
/**
* A beantype proxy is asked to be released. We can only release ones that were not in the permanent set that we initialized with. Those in the
* permanent set can't be changed so we can't release them.
*
* Answer whether it can be released from the server too.
*
* NOTE: Package protected since only REMStandardBeanProxyFactory should call it.
*/
boolean releaseProxy(IBeanTypeProxy proxy) {
/**
* Currently we won't allow any bean type proxies to be released. We don't have a good strategy for handling that there may be hard refs from
* subtypes. One thought is that beanproxies table should store SoftReferences so that only when space is needed, that any beantype that
* doesn't have a subtype (since subtypes hold a strong ref) or, is in the permanent table (since that is hardref) could be GC'd. Then what
* would happen is on releaseProxy we don't actually release, we change it to a WeakRef so that it would definitely be released on a GC. These
* are complicated arch. and we're not sure if it should be allowed or not. So for now, we don't allow them to be released. if
* (!fPermanentProxies.contains(proxy)) { // We can release it. It is not one of the permanent ones. synchronized(this) {
* fBeanProxies.remove(proxy.getTypeName()); return true; } }
*/
return false;
}
/*
* Terminate this factory. Since all of the proxies are registered in the proxy factory, there is no need to release them here. There is no need
* to clear out any fields since this factory will not be held onto by anything and so it will be GC'd.
*/
public void terminateFactory(boolean wait) {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isBeanTypeRegistered(String)
*/
public synchronized boolean isBeanTypeRegistered(String className) {
return fBeanProxies.containsKey(MapTypes.getJNIFormatName(className));
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#registeredTypes()
*/
public Set registeredTypes() {
return fBeanProxies.keySet();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isBeanTypeNotFound(String)
*/
public synchronized boolean isBeanTypeNotFound(String className) {
return fNotFoundTypes != null && fNotFoundTypes.contains(MapTypes.getJNIFormatName(className));
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isMaintainNotFoundTypes()
*/
public synchronized boolean isMaintainNotFoundTypes() {
return fNotFoundTypes != null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#setMaintainNotFoundTypes(boolean)
*/
public synchronized void setMaintainNotFoundTypes(boolean maintain) {
if (maintain) {
if (fNotFoundTypes == null)
fNotFoundTypes = new HashSet();
} else
fNotFoundTypes = null;
}
}