| /******************************************************************************* |
| * 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.core; |
| /* |
| |
| |
| */ |
| |
| |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| |
| import org.eclipse.jem.util.TimerTests; |
| |
| /** |
| * Registry of proxy factories on a per-VM basis. |
| * There can be multiple VM's, this would be required by the |
| * desktop because more than one project could be open, and each |
| * would require their own VM because the classpaths would be different. |
| * This class may be subclassed to provide more factories for a particular |
| * VM. |
| * Creation date: (3/13/00 10:48:10 AM) |
| * @author: Richard Lee Kulp |
| */ |
| public abstract class ProxyFactoryRegistry { |
| |
| protected boolean fIsValid = true; // The registry is valid until terminated. |
| protected ListenerList registryListeners = new ListenerList(); |
| |
| /** |
| * IRegistryListener |
| * Listen for the registry being terminated. |
| */ |
| public interface IRegistryListener { |
| /** |
| * Method registryTerminated. |
| * |
| * The registry has been terminated. When this is called the registry |
| * is no longer valid. It should not be assumed any calls can be made |
| * to the registry. |
| * |
| * @param registry |
| */ |
| public void registryTerminated(ProxyFactoryRegistry registry); |
| } |
| |
| |
| // Factory registration IS NOT a dynamic registration. Once registered for a VM or an instance |
| // they should not be changed. This is because references are cached in other objects. |
| // The VM associated with this Registry shouldn't exited and restarted because |
| // the cached object will then have invalid references to no longer existing objects. |
| // If the VM needs to be restarted, then all proxies need to be tossed. |
| |
| // |
| // Individual ProxyFactoryRegistry, applies to a particular VM. |
| // |
| |
| // *************************** |
| // |
| // IBeanProxyFactory Registry |
| // |
| |
| // The standard bean proxy factory, the one the desktop will use for packages that have not |
| // been extended and registered by customization developers. |
| protected IStandardBeanProxyFactory fCurrentStandardBeanProxyFactory; |
| |
| // The directory of registered extension factories, typically registered by package. |
| final protected Hashtable fRegisteredExtensionBeanProxyFactories = new Hashtable(); |
| |
| // *************************** |
| // |
| // IBeanTypeProxyFactory Registry |
| // |
| |
| // The standard bean type proxy factory, the one the desktop will use for packages that have not |
| // been extended and registered by customization developers. |
| protected IStandardBeanTypeProxyFactory fCurrentStandardBeanTypeProxyFactory; |
| |
| // The directory of registered extension factories, typically registered by package. |
| final protected Hashtable fRegisteredExtensionBeanTypeProxyFactories = new Hashtable(); |
| |
| |
| // *************************** |
| // |
| // Other factories |
| // |
| |
| protected IMethodProxyFactory fMethodProxyFactory = null; // Method Proxy Factory |
| |
| // *************************** |
| // |
| // Constants Registry. Different extensions can store |
| // objects by key as a registry of constants. |
| // For example, java.awt extension will store an object |
| // which has some pre-fetched method proxies stored in it so |
| // that they don't need to be continually recreated. |
| // |
| // This feature should be used with care, so that |
| // only proxies that really need to be cached should |
| // be cached. |
| // |
| // Don't store proxies to live beans in here because |
| // those will be created and destroyed over and over, |
| // and the instance in this cache will get stale. |
| // Should only store things like often used method |
| // proxies that once created are rarely changed. |
| // |
| // Since the proxies can be on any VM, you should have |
| // an interface defining what's available in your |
| // constants entry, and access it through that. |
| |
| protected final Hashtable fRegisteredConstants = new Hashtable(); |
| |
| /** |
| * ProxyFactoryRegistry constructor comment. |
| */ |
| public ProxyFactoryRegistry() { |
| super(); |
| } |
| |
| /** |
| * Method addRegistryListener. |
| * @param listener |
| */ |
| public void addRegistryListener(IRegistryListener listener) { |
| registryListeners.add(listener); |
| } |
| |
| /** |
| * Method removeRegistryListener. |
| * @param listener |
| */ |
| public void removeRegistryListener(IRegistryListener listener) { |
| registryListeners.remove(listener); |
| } |
| |
| protected void fireRegistryTerminated() { |
| if (!registryListeners.isEmpty()) { |
| Object[] list = registryListeners.getListeners(); |
| for (int i = 0; i < list.length; i++) { |
| ((IRegistryListener) list[i]).registryTerminated(this); |
| } |
| } |
| } |
| |
| /** |
| Return the current factory to be used for creating IBeanProxy instances |
| */ |
| public IStandardBeanProxyFactory getBeanProxyFactory() { |
| if (fCurrentStandardBeanProxyFactory == null) { |
| throw new RuntimeException(ProxyMessages.ProxyFactory_EXC__NoBeanProxyFactory); |
| } |
| return fCurrentStandardBeanProxyFactory; |
| } |
| /** |
| Return the current registered bean proxy factory to be used for creating IBeanProxy instances |
| */ |
| public IBeanProxyFactory getBeanProxyFactoryExtension(String packageName) { |
| return (IBeanProxyFactory)fRegisteredExtensionBeanProxyFactories.get(packageName); |
| } |
| |
| /** |
| Return the current factory to be used for creating IBeanTypeProxy instances |
| */ |
| public IStandardBeanTypeProxyFactory getBeanTypeProxyFactory() { |
| if (fCurrentStandardBeanTypeProxyFactory == null) { |
| throw new RuntimeException(ProxyMessages.ProxyFactory_EXC__NoBeanTypeProxyFactory); |
| } |
| return fCurrentStandardBeanTypeProxyFactory; |
| } |
| /** |
| Return the current registered bean type proxy factory to be used for creating IBeanTypeProxy instances |
| */ |
| public IBeanTypeProxyFactory getBeanTypeProxyFactoryExtension(String packageName) { |
| return (IBeanTypeProxyFactory)fRegisteredExtensionBeanTypeProxyFactories.get(packageName); |
| } |
| /** |
| * Return the requested constants entry |
| */ |
| public Object getConstants(Object key) { |
| return fRegisteredConstants.get(key); |
| } |
| /** |
| * Return the MethodProxyFactory for this VM. |
| * Creation date: (3/13/00 10:54:59 AM) |
| * @return org.eclipse.jem.internal.proxy.core.IMethodProxyFactory |
| */ |
| public IMethodProxyFactory getMethodProxyFactory() { |
| return fMethodProxyFactory; |
| } |
| |
| |
| /** |
| * Set the requested constants entry for this VM. |
| */ |
| public void registerConstants(Object key, Object constant) { |
| fRegisteredConstants.put(key, constant); |
| } |
| |
| /** |
| * Remove the constants for the given key. |
| * @param key |
| * |
| * @since 1.1.0 |
| */ |
| public void deregisterConstants(Object key) { |
| fRegisteredConstants.remove(key); |
| } |
| /** |
| * Release the proxy, no longer needed. |
| * This is a helper method to easily access the release from the bean proxy factory. |
| */ |
| public void releaseProxy(IBeanProxy proxy) { |
| // To simply things if release is called when the factory is down (invalid), then just |
| // go on because the proxy is already released. |
| if (fCurrentStandardBeanProxyFactory != null) |
| fCurrentStandardBeanProxyFactory.releaseProxy(proxy); |
| } |
| |
| /** |
| * Is this a valid registry, i.e. is it not terminated. |
| */ |
| public boolean isValid() { |
| return fIsValid; |
| } |
| |
| /** |
| * Terminate the registry without waiting. |
| * <p> |
| * Terminate the registry, but don't necessarily wait for it. |
| * |
| * @see #terminateRegistry(boolean) |
| * @since 1.0.0 |
| */ |
| public final void terminateRegistry() { |
| terminateRegistry(false); |
| } |
| |
| /** |
| * Terminate the registry. |
| * <p> |
| * This will go through each factory and terminate it, and |
| * let the subclass terminate. It will then remove all of the factories so that |
| * if there are any proxies still hanging around they won't hold onto everything, |
| * just the this registry will be held onto. |
| *<p> |
| * Note during termination, the factories should not reference any other factory. |
| * It can assume that the factories will take care of themselves and they should |
| * only release their resources. |
| * <p> |
| * The constants registry will not be terminated because they aren't factories. |
| * However, they will be cleared (no longer referenced) from here so that they |
| * can be GC'd. |
| * |
| * @param wait <code>true</code> to wait for complete termination, <code>false</code> to kick off termination but return ASAP. |
| * @since 1.0.2 |
| */ |
| public final void terminateRegistry(boolean wait) { |
| if (!fIsValid) |
| return; // Already or are already terminating. Don't do it again and don't notify again. |
| fIsValid = false; |
| if (fCurrentStandardBeanTypeProxyFactory != null) { |
| // TimerTests.basicTest.startStep("Terminate Bean Type Factory"); |
| fCurrentStandardBeanTypeProxyFactory.terminateFactory(wait); |
| // TimerTests.basicTest.stopStep("Terminate Bean Type Factory"); |
| fCurrentStandardBeanTypeProxyFactory = null; |
| } |
| if (fCurrentStandardBeanProxyFactory != null) { |
| fCurrentStandardBeanProxyFactory.terminateFactory(wait); |
| fCurrentStandardBeanProxyFactory = null; |
| } |
| if (fMethodProxyFactory != null) { |
| fMethodProxyFactory.terminateFactory(wait); |
| fMethodProxyFactory = null; |
| } |
| |
| Iterator itr = fRegisteredExtensionBeanTypeProxyFactories.values().iterator(); |
| while (itr.hasNext()) { |
| ((IBeanProxyFactory) itr.next()).terminateFactory(wait); |
| } |
| fRegisteredExtensionBeanTypeProxyFactories.clear(); |
| |
| itr = fRegisteredExtensionBeanProxyFactories.values().iterator(); |
| while (itr.hasNext()) { |
| ((IBeanProxyFactory) itr.next()).terminateFactory(wait); |
| } |
| fRegisteredExtensionBeanProxyFactories.clear(); |
| |
| fRegisteredConstants.clear(); |
| |
| TimerTests.basicTest.startStep("Registry Terminated"); //$NON-NLS-1$ |
| registryTerminated(wait); |
| TimerTests.basicTest.stopStep("Registry Terminated"); //$NON-NLS-1$ |
| |
| // TimerTests.basicTest.startStep("Registry Terminated Notification"); |
| fireRegistryTerminated(); // Let everyone know that we are gone. This is fired even if wait is false because at this point in time the registry is invalid. |
| // TimerTests.basicTest.stopStep("Registry Terminated Notification"); |
| } |
| |
| |
| /** |
| * Terminate the Registry. |
| * <p> |
| * It is up to each registry to determine what this means. |
| * <p> |
| * The wait parm is a suggestion if it is <code>false</code>, but it must be honoured if <code>true</code> |
| * |
| * @param wait wait for registry to terminate flag. |
| * |
| * @since 1.0.2 |
| */ |
| protected abstract void registryTerminated(boolean wait); |
| |
| /** |
| * Get the callback registry. |
| */ |
| public abstract ICallbackRegistry getCallbackRegistry(); |
| |
| } |