| /******************************************************************************* |
| * Copyright (c) 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 |
| *******************************************************************************/ |
| /* |
| * $RCSfile: REMProxyConstants.java,v $ |
| * $Revision: 1.6 $ $Date: 2005/05/18 23:11:26 $ |
| */ |
| package org.eclipse.jem.internal.proxy.remote; |
| |
| import java.util.*; |
| import java.util.Map.Entry; |
| |
| import org.eclipse.jem.internal.proxy.core.*; |
| import org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyEvent; |
| |
| |
| |
| |
| /** |
| * MethodProxyConstants is a cache of IMethodProxies to avoid repeated lookup |
| * and thereby avoid the relatively expensive java.lang.reflect calls to repeatedly |
| * lookup method by name |
| * |
| * @since 1.1.0 |
| */ |
| public class REMProxyConstants { |
| |
| private Map methodsCache = new HashMap(80); |
| private Map invokablesCache = new HashMap(80); |
| private Map fieldsCache = new HashMap(80); |
| |
| private REMProxyFactoryRegistry registry; |
| |
| public REMProxyConstants(REMProxyFactoryRegistry registry) { |
| this.registry = registry; |
| } |
| |
| /* |
| * Used as the key to the methodCache and invokablesCache when there are parms. |
| * It allows the parms to be either strings or IBeanTypeProxies without the |
| * overhead of creating complicated strings. |
| * |
| * It will compare method name and each individual parm name without fluffing |
| * up a string and building it up. |
| * |
| * For no parm methods, just the name of the method as a string will be the key. |
| * |
| * @since 1.1.0 |
| */ |
| private abstract static class MethodKey { |
| public String methodName; |
| public MethodKey(String methodName) { |
| this.methodName = methodName; |
| } |
| |
| protected abstract boolean compareParms(IProxyBeanType[] parms); |
| protected abstract boolean compareParms(String[] parms); |
| |
| |
| /* (non-Javadoc) |
| * @see java.lang.Object#hashCode() |
| */ |
| public int hashCode() { |
| return methodName.hashCode(); |
| } |
| } |
| |
| private static class MethodKeyStringParms extends MethodKey { |
| public String[] parmNames; |
| |
| public MethodKeyStringParms(String methodName, String[] parmNames) { |
| super(methodName); |
| this.parmNames = parmNames; |
| } |
| |
| /* (non-Javadoc) |
| * @see java.lang.Object#equals(java.lang.Object) |
| */ |
| public boolean equals(Object obj) { |
| if (this == obj) |
| return true; |
| try { |
| return ((MethodKey) obj).compareParms(parmNames); |
| } catch (ClassCastException e) { |
| return false; |
| } |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jem.internal.proxy.remote.REMProxyConstants.MethodKey#hashCode() |
| */ |
| public int hashCode() { |
| int h = super.hashCode(); |
| for (int i = 0; i < parmNames.length; i++) { |
| h += parmNames[i].hashCode(); |
| } |
| return h; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jem.internal.proxy.remote.REMProxyConstants.MethodKey#compareParms(org.eclipse.jem.internal.proxy.core.IBeanTypeProxy[]) |
| */ |
| protected boolean compareParms(IProxyBeanType[] parms) { |
| if (parms.length != parmNames.length) |
| return false; |
| for (int i = 0; i < parms.length; i++) { |
| if (!parms[i].getTypeName().equals(parmNames[i])) |
| return false; |
| } |
| return true; |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jem.internal.proxy.remote.REMProxyConstants.MethodKey#compareParms(java.lang.String[]) |
| */ |
| protected boolean compareParms(String[] parms) { |
| return Arrays.equals(parms, parmNames); |
| } |
| } |
| |
| private static class MethodKeyProxyParms extends MethodKey { |
| public IProxyBeanType[] parmTypes; |
| |
| public MethodKeyProxyParms(String methodName, IProxyBeanType[] parmTypes) { |
| super(methodName); |
| this.parmTypes = parmTypes; |
| } |
| |
| public Object toMethodKeyStringParms() { |
| String[] parms = new String[parmTypes.length]; |
| for (int i = 0; i < parmTypes.length; i++) { |
| parms[i] = parmTypes[i].getTypeName(); |
| } |
| return new MethodKeyStringParms(methodName, parms); |
| } |
| |
| /* (non-Javadoc) |
| * @see java.lang.Object#equals(java.lang.Object) |
| */ |
| public boolean equals(Object obj) { |
| if (this == obj) |
| return true; |
| try { |
| return ((MethodKey) obj).compareParms(parmTypes); |
| } catch (ClassCastException e) { |
| return false; |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jem.internal.proxy.remote.REMProxyConstants.MethodKey#hashCode() |
| */ |
| public int hashCode() { |
| int h = super.hashCode(); |
| for (int i = 0; i < parmTypes.length; i++) { |
| h += parmTypes[i].getTypeName().hashCode(); |
| } |
| return h; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jem.internal.proxy.remote.REMProxyConstants.MethodKey#compareParms(org.eclipse.jem.internal.proxy.core.IBeanTypeProxy[]) |
| */ |
| protected boolean compareParms(String[] parms) { |
| if (parms.length != parmTypes.length) |
| return false; |
| for (int i = 0; i < parms.length; i++) { |
| if (!parmTypes[i].getTypeName().equals(parms[i])) |
| return false; |
| } |
| return true; |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jem.internal.proxy.remote.REMProxyConstants.MethodKey#compareParms(java.lang.String[]) |
| */ |
| protected boolean compareParms(IProxyBeanType[] parms) { |
| if (parms.length != parmTypes.length) |
| return false; |
| for (int i = 0; i < parms.length; i++) { |
| if (!parmTypes[i].getTypeName().equals(parms[i].getTypeName())) |
| return false; |
| } |
| return true; |
| } |
| } |
| |
| static int REMMETHODCOUNT = 0; |
| static int UNIQUEMETHODCOUNT = 0; |
| static int REMINVOKABLECOUNT = 0; |
| static int UNIQUEINVOKABLECOUNT = 0; |
| static int INVOKEINVOKECOUNT = 0; |
| static int METHODPROXYINVOKECOUNT = 0; |
| static int REMFIELDCOUNT = 0; |
| static int UNIQUEFIELDCOUNT = 0; |
| static int REMCONSTRUCTORCALLED = 0; |
| static HashMap METHODCOUNTMAP; |
| static HashMap FIELDCOUNTMAP; |
| static HashMap FIELDSETCOUNTMAP; |
| static boolean GATHER_COUNTS; |
| |
| /** |
| * Set if counts should be gathered. |
| * |
| * @param gatherCounts |
| * |
| * @since 1.1.0 |
| */ |
| public static void setGatherCounts(boolean gatherCounts) { |
| if (gatherCounts != GATHER_COUNTS) { |
| reset(); |
| if (gatherCounts) { |
| if (METHODCOUNTMAP == null) { |
| METHODCOUNTMAP = new HashMap(); |
| FIELDCOUNTMAP = new HashMap(); |
| FIELDSETCOUNTMAP = new HashMap(); |
| } |
| } |
| GATHER_COUNTS = gatherCounts; |
| } |
| } |
| |
| |
| public static void reset(){ |
| REMMETHODCOUNT = UNIQUEMETHODCOUNT = REMINVOKABLECOUNT = UNIQUEINVOKABLECOUNT = REMCONSTRUCTORCALLED = METHODPROXYINVOKECOUNT = INVOKEINVOKECOUNT = REMFIELDCOUNT = UNIQUEFIELDCOUNT = 0; |
| if (GATHER_COUNTS) { |
| METHODCOUNTMAP.clear(); |
| FIELDCOUNTMAP.clear(); |
| FIELDSETCOUNTMAP.clear(); |
| } |
| } |
| |
| public static void println(){ |
| |
| if (GATHER_COUNTS) { |
| System.out.println("--------------------------------------------------"); //$NON-NLS-1$ |
| System.out.println("Method proxies invokes = " + METHODPROXYINVOKECOUNT); //$NON-NLS-1$ |
| System.out.println("Invoke invokes = " + INVOKEINVOKECOUNT); //$NON-NLS-1$ |
| System.out.println(".................................................."); //$NON-NLS-1$ |
| System.out.println("Methods retrieved = " + REMMETHODCOUNT + "(" + UNIQUEMETHODCOUNT + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| System.out.println("Invokes retrieved = " + REMINVOKABLECOUNT + "(" + UNIQUEINVOKABLECOUNT + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| System.out.println("Fields retrieved = " + REMFIELDCOUNT + "(" + UNIQUEFIELDCOUNT + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| System.out.println("Constructor calls = " + REMCONSTRUCTORCALLED); //$NON-NLS-1$ |
| System.out.println("--------------------------------------------------"); //$NON-NLS-1$ |
| System.out.println("-Count of methods invoked-------------------------"); //$NON-NLS-1$ |
| System.out.println("--------------------------------------------------"); //$NON-NLS-1$ |
| |
| // Collate the methods called |
| Iterator entries = METHODCOUNTMAP.entrySet().iterator(); |
| while (entries.hasNext()) { |
| Map.Entry entry = (Entry) entries.next(); |
| REMMethodProxy methodProxy = (REMMethodProxy) entry.getKey(); |
| System.out.println(methodProxy.getClassType().getTypeName() + "," + methodProxy.getName() + "," + entry.getValue()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| System.out.println("--------------------------------------------------"); //$NON-NLS-1$ |
| System.out.println("-Count of fields get called ----------------------"); //$NON-NLS-1$ |
| System.out.println("--------------------------------------------------"); //$NON-NLS-1$ |
| |
| // Collate the fields accessed |
| entries = FIELDCOUNTMAP.entrySet().iterator(); |
| while (entries.hasNext()) { |
| Map.Entry entry = (Entry) entries.next(); |
| REMFieldProxy fieldProxy = (REMFieldProxy) entry.getKey(); |
| System.out.println(fieldProxy.toBeanString() + "," + entry.getValue()); //$NON-NLS-1$ |
| } |
| |
| System.out.println("--------------------------------------------------"); //$NON-NLS-1$ |
| System.out.println("-Count of fields set called ----------------------"); //$NON-NLS-1$ |
| System.out.println("--------------------------------------------------"); //$NON-NLS-1$ |
| |
| // Collate the fields set |
| entries = FIELDSETCOUNTMAP.entrySet().iterator(); |
| while (entries.hasNext()) { |
| Map.Entry entry = (Entry) entries.next(); |
| REMFieldProxy fieldProxy = (REMFieldProxy) entry.getKey(); |
| System.out.println(fieldProxy.toBeanString() + "," + entry.getValue()); //$NON-NLS-1$ |
| } |
| } |
| |
| } |
| |
| /** |
| * @param aBeanTypeProxy = BeanTypeProxy for the method |
| * @param methodName = methodName to be looked for |
| * @param parmTypes = array of qualified type names for the method arguments, null if no methods |
| */ |
| public IMethodProxy getMethodProxy(IBeanTypeProxy aBeanTypeProxy, String methodName, String[] parmTypes){ |
| if (!registry.isValid()) |
| return null; |
| |
| REMMETHODCOUNT++; |
| Map methods; |
| Object key; |
| synchronized (this) { |
| // The classCache map is keyed by the BeanTypeProxy and holds a further map of cache'd methods |
| methods = getMethods(aBeanTypeProxy); |
| |
| // The syntax of the key is methodName(parmType1,parmType2) |
| if (parmTypes == null || parmTypes.length == 0) { |
| key = methodName; |
| } else { |
| key = new MethodKeyStringParms(methodName, parmTypes); |
| } |
| |
| IMethodProxy result = (IMethodProxy) methods.get(key); |
| if (result != null) |
| return result; |
| } |
| |
| UNIQUEMETHODCOUNT++; |
| // Get the method proxy and cache this before returning it |
| // Get the method proxy and cache this before returning it |
| REMMethodProxyFactory proxyFactory = (REMMethodProxyFactory) registry.getMethodProxyFactory(); |
| IMethodProxy result = proxyFactory.getMethodProxy((IREMBeanTypeProxy)aBeanTypeProxy,methodName,parmTypes); |
| synchronized (this) { |
| // Get it again to make sure it hasn't changed due to a race condition. We don't sync for the getMethodProxy because that goes to the remote vm and could deadlock. |
| IMethodProxy mValue = (IMethodProxy) methods.get(key); |
| if (mValue != null && mValue != result) { |
| registry.releaseProxy(result); // Don't need the result now, got it through a race condition. |
| return mValue; // We have a real value now. |
| } |
| methods.put(key, result); |
| } |
| return result; |
| } |
| /** |
| * @param aBeanTypeProxy |
| * @return Map of cache'd methods |
| */ |
| private Map getMethods(IProxyBeanType aBeanTypeProxy) { |
| Map methods = (Map) methodsCache.get(aBeanTypeProxy.getTypeName()); |
| if(methods == null){ |
| methods = new HashMap(20); |
| methodsCache.put(aBeanTypeProxy.getTypeName(),methods); |
| } |
| return methods; |
| } |
| /** |
| * @param aBeanTypeProxy |
| * @return Map of cache'd invokables |
| */ |
| private Map getInvokables(IBeanTypeProxy aBeanTypeProxy) { |
| Map invokables = (Map) invokablesCache.get(aBeanTypeProxy); |
| if(invokables == null){ |
| invokables = new HashMap(20); |
| invokablesCache.put(aBeanTypeProxy,invokables); |
| } |
| return invokables; |
| } |
| /** |
| * @param aBeanTypeProxy |
| * @return Map of cache'd fields |
| */ |
| private Map getFields(IProxyBeanType aBeanTypeProxy) { |
| Map fields = (Map) fieldsCache.get(aBeanTypeProxy.getTypeName()); |
| if(fields == null){ |
| fields = new HashMap(20); |
| fieldsCache.put(aBeanTypeProxy.getTypeName(),fields); |
| } |
| return fields; |
| } |
| /** |
| * @param aBeanTypeProxy = BeanTypeProxy for the method |
| * @param methodName = methodName to be looked for |
| * @param parmTypes = array of qualified type names for the method arguments, null if no arguments |
| */ |
| public IInvokable getInvokable(IBeanTypeProxy aBeanTypeProxy, String invokableName, String[] parmTypeNames){ |
| |
| REMINVOKABLECOUNT++; |
| // The classCache map is keyed by the BeanTypeProxy and holds a further map of cache'd methods |
| Map invokables = getInvokables(aBeanTypeProxy); |
| |
| Object key = null; |
| if(parmTypeNames == null || parmTypeNames.length == 0){ |
| key = invokableName; |
| } else { |
| key = new MethodKeyStringParms(invokableName, parmTypeNames); |
| } |
| |
| IInvokable result = (IInvokable) invokables.get(key); |
| if(result != null) return result; |
| |
| UNIQUEINVOKABLECOUNT++; |
| // Get the method proxy and cache this before returning it |
| // Get the method proxy and cache this before returning it |
| REMMethodProxyFactory proxyFactory = (REMMethodProxyFactory) aBeanTypeProxy.getProxyFactoryRegistry().getMethodProxyFactory(); |
| result = proxyFactory.getInvokable((IREMBeanTypeProxy)aBeanTypeProxy,invokableName,parmTypeNames); |
| invokables.put(key,result); |
| return result; |
| |
| } |
| /** |
| * @param aBeanTypeProxy = BeanTypeProxy for the method |
| * @param methodName = methodName to be looked for |
| * @param parmTypes = array of IBeanTypeProxy types for the method arguments, null if no arguments |
| */ |
| public IInvokable getInvokable(IBeanTypeProxy aBeanTypeProxy, String invokableName, IBeanTypeProxy[] parmTypes){ |
| |
| REMINVOKABLECOUNT++; |
| // The classCache map is keyed by the BeanTypeProxy and holds a further map of cache'd methods |
| Map invokables = getInvokables(aBeanTypeProxy); |
| |
| Object key = null; |
| if(parmTypes == null || parmTypes.length == 0){ |
| key = invokableName; |
| } else { |
| key = new MethodKeyProxyParms(invokableName, parmTypes); |
| } |
| |
| IInvokable result = (IInvokable) invokables.get(key); |
| if(result != null) return result; |
| |
| UNIQUEINVOKABLECOUNT++; |
| // Get the method proxy and cache this before returning it |
| // Get the method proxy and cache this before returning it |
| REMMethodProxyFactory proxyFactory = (REMMethodProxyFactory) aBeanTypeProxy.getProxyFactoryRegistry().getMethodProxyFactory(); |
| result = proxyFactory.getInvokable((IREMBeanTypeProxy)aBeanTypeProxy,invokableName,parmTypes); |
| invokables.put(key,result); |
| return result; |
| |
| } |
| /** |
| * @param aBeanTypeProxy = BeanTypeProxy for the method |
| * @param methodName = methodName to be looked for |
| * @param parmTypes = array of qualified type names for the method arguments, null if no methods |
| */ |
| public IMethodProxy getMethodProxy(IBeanTypeProxy aBeanTypeProxy, String methodName, IBeanTypeProxy[] parmTypes){ |
| if (!registry.isValid()) |
| return null; |
| |
| REMMETHODCOUNT++; |
| // The classCache map is keyed by the BeanTypeProxy and holds a further map of cache'd methods |
| Map methods; |
| Object key; |
| synchronized (this) { |
| methods = getMethods(aBeanTypeProxy); |
| |
| key = null; |
| if (parmTypes == null || parmTypes.length == 0) { |
| key = methodName; |
| } else { |
| key = new MethodKeyProxyParms(methodName, parmTypes); |
| } |
| |
| IMethodProxy result = (IMethodProxy) methods.get(key); |
| if (result != null) |
| return result; |
| } |
| |
| UNIQUEMETHODCOUNT++; |
| // Get the method proxy and cache this before returning it |
| // Get the method proxy and cache this before returning it |
| REMMethodProxyFactory proxyFactory = (REMMethodProxyFactory) registry.getMethodProxyFactory(); |
| IMethodProxy result = proxyFactory.getMethodProxy((IREMBeanTypeProxy)aBeanTypeProxy,methodName,parmTypes); |
| synchronized (this) { |
| // Get it again to make sure it hasn't changed due to a race condition. We don't sync for the getMethodProxy because that goes to the remote vm and could deadlock. |
| IMethodProxy mValue = (IMethodProxy) methods.get(key); |
| if (mValue != null && mValue != result) { |
| registry.releaseProxy(result); // Don't need result now, got it already through a race condition. |
| return mValue; // We have a real value now. |
| } |
| methods.put(key, result); |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Return the proxy method for the method through the expression. |
| * @param expression |
| * @param aBeanTypeProxy |
| * @param methodName |
| * @param parmTypes |
| * @return either the IMethodProxy if already resolved or an ExpressionProxy if not yet resolved. |
| * |
| * @since 1.1.0 |
| */ |
| public IProxyMethod getMethodProxy(IExpression expression, IProxyBeanType aBeanTypeProxy, String methodName, IProxyBeanType[] parmTypes){ |
| if (!registry.isValid()) |
| return null; |
| |
| REMMETHODCOUNT++; |
| Map methods; |
| Map epMethods; |
| Object key; |
| boolean isKey; |
| synchronized (this) { |
| // The classCache map is keyed by the BeanTypeProxy name and holds a further map of cache'd methods |
| methods = getMethods(aBeanTypeProxy); |
| |
| if (parmTypes == null || parmTypes.length == 0) { |
| key = methodName; |
| isKey = false; |
| } else { |
| key = new MethodKeyProxyParms(methodName, parmTypes); |
| isKey = true; |
| } |
| |
| IProxyMethod result = (IProxyMethod) methods.get(key); |
| if (result != null) |
| return result; |
| |
| // See if stored in the expression. |
| epMethods = ((REMExpression) expression).getMethods(aBeanTypeProxy); |
| result = (IProxyMethod) epMethods.get(key); |
| if (result != null) |
| return result; |
| } |
| |
| UNIQUEMETHODCOUNT++; |
| // Get the method expression proxy and cache this before returning it |
| IProxyMethod result = ((Expression) expression).createMethodExpressionProxy(aBeanTypeProxy,methodName,parmTypes); |
| epMethods.put(key, result); |
| final Object epKey = key; |
| final Map rMethods = methods; |
| final Map fepMethods = epMethods; |
| final boolean isKeyType = isKey; |
| ((ExpressionProxy) result).addProxyListener(new ExpressionProxy.ProxyAdapter() { |
| public void proxyResolved(ProxyEvent event) { |
| synchronized (REMProxyConstants.this) { |
| if (rMethods.containsKey(epKey)) |
| return; // We already have a true method proxy in there. A race condition occurred. |
| |
| // Now put this resolved guy into the methods. |
| // We don't want the key to contain expression proxies in the final map, so if it is a key type |
| // we will turn it into a string type key. |
| Object key; |
| if (isKeyType) { |
| key = ((MethodKeyProxyParms) epKey).toMethodKeyStringParms(); // So that we don't put a ket that contains expression proxy parm types into the main map. |
| } else |
| key = epKey; |
| |
| rMethods.put(key, event.getProxy()); |
| } |
| } |
| |
| public void proxyNotResolved(ExpressionProxy.ProxyEvent event) { |
| synchronized (REMProxyConstants.this) { |
| fepMethods.remove(epKey); |
| } |
| } |
| |
| }); |
| return result; |
| } |
| |
| /** |
| * @param proxy |
| */ |
| static void methodInvoked(REMMethodProxy proxy) { |
| |
| if (GATHER_COUNTS) { |
| Integer count = (Integer) METHODCOUNTMAP.get(proxy); |
| if (count == null) { |
| METHODCOUNTMAP.put(proxy, new Integer(1)); |
| } else { |
| METHODCOUNTMAP.put(proxy, new Integer(count.intValue() + 1)); |
| } |
| } |
| } |
| |
| static void fieldGetInvoked(IBeanProxy proxy) { |
| |
| if (GATHER_COUNTS) { |
| Integer count = (Integer) FIELDCOUNTMAP.get(proxy); |
| if (count == null) { |
| FIELDCOUNTMAP.put(proxy, new Integer(1)); |
| } else { |
| FIELDCOUNTMAP.put(proxy, new Integer(count.intValue() + 1)); |
| } |
| } |
| } |
| |
| static void fieldSetInvoked(IBeanProxy proxy, IBeanProxy value) { |
| |
| if (GATHER_COUNTS) { |
| Integer count = (Integer) FIELDSETCOUNTMAP.get(proxy); |
| if (count == null) { |
| FIELDSETCOUNTMAP.put(proxy, new Integer(1)); |
| } else { |
| FIELDSETCOUNTMAP.put(proxy, new Integer(count.intValue() + 1)); |
| } |
| } |
| } |
| |
| /** |
| * @param proxy for the BeanType of the field |
| * @param fieldName of the field, e.g. (java.awt.Dimension, width) for the "width" field on Dimension |
| * @return The field proxy that is cache'd for performance |
| */ |
| public IFieldProxy getFieldProxy(REMAbstractBeanTypeProxy aBeanTypeProxy, String fieldName) { |
| if (!registry.isValid()) |
| return null; |
| |
| REMFIELDCOUNT++; |
| Map fields; |
| synchronized (this) { |
| // The field map is keyed by the BeanTypeProxy and holds a further map of cache'd fields |
| fields = getFields(aBeanTypeProxy); |
| |
| // Lookup the cache'd Field proxy |
| IFieldProxy result = (IFieldProxy) fields.get(fieldName); |
| if (result != null) |
| return result; |
| } |
| |
| UNIQUEFIELDCOUNT++; |
| IFieldProxy result = (IFieldProxy) REMStandardBeanProxyConstants.getConstants(aBeanTypeProxy.getProxyFactoryRegistry()).getClassGetField().invokeCatchThrowableExceptions( |
| aBeanTypeProxy, |
| registry.getBeanProxyFactory().createBeanProxyWith(fieldName)); |
| synchronized (this) { |
| IFieldProxy fValue = (IFieldProxy) fields.get(fieldName); |
| if (fValue != null) { |
| registry.releaseProxy(result); // Don't need it now. A race had put another one in. |
| return fValue; |
| } |
| fields.put(fieldName,result); |
| } |
| return result; |
| } |
| |
| public IProxyField getFieldProxy(IExpression expression, IProxyBeanType aBeanTypeProxy, final String fieldName){ |
| if (!registry.isValid()) |
| return null; |
| |
| REMFIELDCOUNT++; |
| Map fields; |
| Map epFields; |
| synchronized (this) { |
| // The classCache map is keyed by the BeanTypeProxy name and holds a further map of cache'd methods |
| fields = getFields(aBeanTypeProxy); |
| |
| IProxyField result = (IProxyField) fields.get(fieldName); |
| if (result != null) |
| return result; |
| |
| // See if stored in the expression. |
| epFields = ((REMExpression) expression).getFields(aBeanTypeProxy); |
| result = (IProxyField) epFields.get(fieldName); |
| if (result != null) |
| return result; |
| } |
| |
| UNIQUEFIELDCOUNT++; |
| // Get the field expression proxy and cache this before returning it |
| IProxyField result = ((REMExpression) expression).createFieldExpressionProxy(aBeanTypeProxy, fieldName); |
| epFields.put(fieldName, result); |
| final Map fpFields = fields; |
| final Map fepFields = epFields; |
| ((ExpressionProxy) result).addProxyListener(new ExpressionProxy.ProxyAdapter() { |
| |
| public void proxyResolved(ProxyEvent event) { |
| synchronized (REMProxyConstants.this) { |
| if (fpFields.containsKey(fieldName)) |
| return; // Already set to resolved value by someone else. |
| fpFields.put(fieldName, event.getProxy()); |
| } |
| } |
| public void proxyNotResolved(ExpressionProxy.ProxyEvent event) { |
| synchronized (REMProxyConstants.this) { |
| fepFields.remove(fieldName); |
| } |
| } |
| }); |
| |
| return result; |
| } |
| } |