/******************************************************************************* * Copyright (c) 2004, 2007 Composent, Inc. 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: * Composent, Inc. - initial API and implementation ******************************************************************************/ package org.eclipse.ecf.core; import java.util.*; import org.eclipse.core.runtime.*; import org.eclipse.ecf.core.identity.ID; import org.eclipse.ecf.core.provider.IContainerInstantiator; import org.eclipse.ecf.core.util.Trace; import org.eclipse.ecf.internal.core.*; /** * Factory for creating {@link IContainer} instances. This class provides ECF * clients an entry point to constructing {@link IContainer} instances. <br> * <br> * Here is an example use of the ContainerFactory to construct an instance of * the 'standalone' container (has no connection to other containers): <br> * <br> * <code> * IContainer container = <br> * ContainerFactory.getDefault().createContainer("ecf.generic.client"); * <br><br> * ...further use of container here... * </code> For more details on the creation * and lifecycle of IContainer instances created via this factory see * {@link IContainer}. * * @see IContainer * @see IContainerFactory * @since 3.1 */ public class ContainerFactory implements IContainerFactory, IContainerManager { public static final String BASE_CONTAINER_NAME = "ecf.base"; //$NON-NLS-1$ static final Map containerdescriptions = new HashMap(); static final Map containers = new HashMap(); static final List managerListeners = new ArrayList(); private static IContainerFactory instance = null; private volatile static boolean init = false; static { instance = new ContainerFactory(); } class ContainerEntry { private final IContainer container; private final ContainerTypeDescription typeDescription; public ContainerEntry(IContainer container, ContainerTypeDescription typeDescription) { this.container = container; this.typeDescription = typeDescription; } public IContainer getContainer() { return this.container; } public ContainerTypeDescription getContainerTypeDescription() { return this.typeDescription; } } public synchronized static IContainerFactory getDefault() { if (init == false) { // first mark the extension initalized because it initializeExtensions() // eventually calls this method again init = true; ECFPlugin.getDefault().initializeExtensions(); } return instance; } protected ContainerFactory() { ECFPlugin.getDefault().addDisposable(new IDisposable() { public void dispose() { synchronized (containers) { for (Iterator i = containers.keySet().iterator(); i.hasNext();) { ContainerEntry entry = (ContainerEntry) containers.get(i.next()); if (entry != null) { IContainer c = entry.getContainer(); try { c.dispose(); } catch (Throwable e) { // Log exception ECFPlugin.getDefault().log(new Status(IStatus.ERROR, ECFPlugin.getDefault().getBundle().getSymbolicName(), IStatus.ERROR, "container dispose error", e)); //$NON-NLS-1$ Trace.catching(ECFPlugin.PLUGIN_ID, ECFDebugOptions.EXCEPTIONS_CATCHING, ContainerFactory.class, "doDispose", e); //$NON-NLS-1$ } } } containers.clear(); } containerdescriptions.clear(); managerListeners.clear(); } }); } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerFactory#addDescription(org.eclipse.ecf.core.ContainerTypeDescription) */ public ContainerTypeDescription addDescription(ContainerTypeDescription containerTypeDescription) { return addDescription0(containerTypeDescription); } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerFactory#getDescriptions() */ public List getDescriptions() { return getDescriptions0(); } protected List getDescriptions0() { synchronized (containerdescriptions) { return new ArrayList(containerdescriptions.values()); } } protected ContainerTypeDescription addDescription0(ContainerTypeDescription containerTypeDescription) { if (containerTypeDescription == null) return null; synchronized (containerdescriptions) { return (ContainerTypeDescription) containerdescriptions.put(containerTypeDescription.getName(), containerTypeDescription); } } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerFactory#containsDescription(org.eclipse.ecf.core.ContainerTypeDescription) */ public boolean containsDescription(ContainerTypeDescription containerTypeDescription) { return containsDescription0(containerTypeDescription); } protected boolean containsDescription0(ContainerTypeDescription containerTypeDescription) { if (containerTypeDescription == null) return false; synchronized (containerdescriptions) { return containerdescriptions.containsKey(containerTypeDescription.getName()); } } protected ContainerTypeDescription getDescription0(ContainerTypeDescription containerTypeDescription) { if (containerTypeDescription == null) return null; synchronized (containerdescriptions) { return (ContainerTypeDescription) containerdescriptions.get(containerTypeDescription.getName()); } } protected ContainerTypeDescription getDescription0(String containerTypeDescriptionName) { if (containerTypeDescriptionName == null) return null; synchronized (containerdescriptions) { return (ContainerTypeDescription) containerdescriptions.get(containerTypeDescriptionName); } } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerFactory#getDescriptionByName(java.lang.String) */ public ContainerTypeDescription getDescriptionByName(String containerTypeDescriptionName) { return getDescription0(containerTypeDescriptionName); } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerFactory#removeDescription(org.eclipse.ecf.core.ContainerTypeDescription) */ public ContainerTypeDescription removeDescription(ContainerTypeDescription containerTypeDescription) { return removeDescription0(containerTypeDescription); } protected ContainerTypeDescription removeDescription0(ContainerTypeDescription containerTypeDescription) { if (containerTypeDescription == null) return null; synchronized (containerdescriptions) { return (ContainerTypeDescription) containerdescriptions.remove(containerTypeDescription.getName()); } } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerFactory#getDescriptionsForContainerAdapter(java.lang.Class) */ public ContainerTypeDescription[] getDescriptionsForContainerAdapter(Class containerAdapter) { if (containerAdapter == null) throw new NullPointerException("containerAdapter cannot be null"); //$NON-NLS-1$ List result = new ArrayList(); List descriptions = getDescriptions(); for (Iterator i = descriptions.iterator(); i.hasNext();) { ContainerTypeDescription description = (ContainerTypeDescription) i.next(); String[] supportedAdapters = description.getSupportedAdapterTypes(); if (supportedAdapters != null) { for (int j = 0; j < supportedAdapters.length; j++) { if (supportedAdapters[j].equals(containerAdapter.getName())) result.add(description); } } } return (ContainerTypeDescription[]) result.toArray(new ContainerTypeDescription[] {}); } protected void throwContainerCreateException(String message, Throwable cause, String method) throws ContainerCreateException { ContainerCreateException except = (cause == null) ? new ContainerCreateException(message) : new ContainerCreateException(message, cause); Trace.throwing(ECFPlugin.PLUGIN_ID, ECFDebugOptions.EXCEPTIONS_THROWING, ContainerFactory.class, method, except); throw except; } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerFactory#createContainer() */ public IContainer createContainer() throws ContainerCreateException { return createContainer(BASE_CONTAINER_NAME); } /* (non-Javadoc) * @see org.eclipse.ecf.core.IContainerFactory#createContainer(org.eclipse.ecf.core.identity.ID) */ public IContainer createContainer(ID containerID) throws ContainerCreateException { if (containerID == null) return createContainer(); return createContainer(BASE_CONTAINER_NAME, new Object[] {containerID}); } /* (non-Javadoc) * @see org.eclipse.ecf.core.IContainerFactory#createContainer(org.eclipse.ecf.core.ContainerTypeDescription) */ public IContainer createContainer(ContainerTypeDescription containerTypeDescription) throws ContainerCreateException { return createContainer(containerTypeDescription, (Object[]) null); } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerFactory#createContainer(java.lang.String) */ public IContainer createContainer(String containerTypeDescriptionName) throws ContainerCreateException { return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), (Object[]) null); } private ContainerTypeDescription getDescriptionByNameWithException(String containerTypeDescriptionName) throws ContainerCreateException { ContainerTypeDescription typeDescription = getDescriptionByName(containerTypeDescriptionName); if (typeDescription == null) throw new ContainerCreateException("Container type description with name=" + containerTypeDescriptionName + " not found. This may indicate that the desired provider is not available or not startable within runtime."); //$NON-NLS-1$ //$NON-NLS-2$ return typeDescription; } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerFactory#createContainer(org.eclipse.ecf.core.ContainerTypeDescription, * java.lang.Object[]) */ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, Object[] parameters) throws ContainerCreateException { String method = "createContainer"; //$NON-NLS-1$ Trace.entering(ECFPlugin.PLUGIN_ID, ECFDebugOptions.METHODS_ENTERING, ContainerFactory.class, method, new Object[] {containerTypeDescription, Trace.getArgumentsString(parameters)}); if (containerTypeDescription == null) throwContainerCreateException("ContainerTypeDescription cannot be null", null, method); //$NON-NLS-1$ ContainerTypeDescription cd = getDescription0(containerTypeDescription); if (cd == null) throwContainerCreateException("ContainerTypeDescription '" //$NON-NLS-1$ + containerTypeDescription.getName() + "' not found", null, method); //$NON-NLS-1$ IContainerInstantiator instantiator = null; try { instantiator = cd.getInstantiator(); } catch (Exception e) { throwContainerCreateException("createContainer cannot get IContainerInstantiator for description : " //$NON-NLS-1$ + containerTypeDescription, e, method); } // Ask instantiator to actually create instance IContainer container = instantiator.createInstance(containerTypeDescription, parameters); if (container == null) throwContainerCreateException("Instantiator returned null for '" //$NON-NLS-1$ + cd.getName() + "'", null, method); //$NON-NLS-1$ // Add to containers map if container.getID() provides a valid value. ID containerID = container.getID(); if (containerID != null) addContainer(container, cd); Trace.exiting(ECFPlugin.PLUGIN_ID, ECFDebugOptions.METHODS_EXITING, ContainerFactory.class, method, container); return container; } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerFactory#createContainer(java.lang.String, * java.lang.Object[]) */ public IContainer createContainer(String containerTypeDescriptionName, Object[] parameters) throws ContainerCreateException { return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), parameters); } /* (non-Javadoc) * @see org.eclipse.ecf.core.IContainerFactory#createContainer(org.eclipse.ecf.core.ContainerTypeDescription, org.eclipse.ecf.core.identity.ID, java.lang.Object[]) */ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, ID containerID, Object[] parameters) throws ContainerCreateException { if (containerID == null) return createContainer(containerTypeDescription, parameters); Object[] params = (parameters == null || parameters.length == 0) ? new Object[1] : new Object[parameters.length + 1]; params[0] = containerID; if (parameters != null && parameters.length != 0) System.arraycopy(parameters, 0, params, 1, parameters.length); return createContainer(containerTypeDescription, params); } /* (non-Javadoc) * @see org.eclipse.ecf.core.IContainerFactory#createContainer(java.lang.String, org.eclipse.ecf.core.identity.ID, java.lang.Object[]) */ public IContainer createContainer(String containerTypeDescriptionName, ID containerID, Object[] parameters) throws ContainerCreateException { if (containerID == null) return createContainer(containerTypeDescriptionName, parameters); return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), containerID, parameters); } /* (non-Javadoc) * @see org.eclipse.ecf.core.IContainerFactory#createContainer(org.eclipse.ecf.core.ContainerTypeDescription, org.eclipse.ecf.core.identity.ID) */ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, ID containerID) throws ContainerCreateException { if (containerID == null) return createContainer(containerTypeDescription); return createContainer(containerTypeDescription, new Object[] {containerID}); } /* (non-Javadoc) * @see org.eclipse.ecf.core.IContainerFactory#createContainer(java.lang.String, org.eclipse.ecf.core.identity.ID) */ public IContainer createContainer(String containerTypeDescriptionName, ID containerID) throws ContainerCreateException { return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), new Object[] {containerID}); } /** * @since 3.1 */ public IContainer createContainer(String containerTypeDescriptionName, String containerId) throws ContainerCreateException { return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), containerId); } /** * @since 3.1 */ public IContainer createContainer(String containerTypeDescriptionName, String containerId, Object[] parameters) throws ContainerCreateException { return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), containerId, parameters); } /** * @since 3.1 */ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, String containerId) throws ContainerCreateException { return createContainer(containerTypeDescription, containerId, (Object[]) null); } /** * @since 3.1 */ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, String containerId, Object[] parameters) throws ContainerCreateException { if (containerId == null) return createContainer(containerTypeDescription, parameters); Object[] params = (parameters == null || parameters.length == 0) ? new Object[1] : new Object[parameters.length + 1]; params[0] = containerId; if (parameters != null && parameters.length != 0) System.arraycopy(parameters, 0, params, 1, parameters.length); return createContainer(containerTypeDescription, params); } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerManager#getAllContainers() */ public IContainer[] getAllContainers() { List containerValues = new ArrayList(); synchronized (containers) { Collection containerEntrys = containers.values(); for (Iterator i = containerEntrys.iterator(); i.hasNext();) { ContainerEntry entry = (ContainerEntry) i.next(); containerValues.add(entry.getContainer()); } } return (IContainer[]) containerValues.toArray(new IContainer[] {}); } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerManager#getContainer(org.eclipse.ecf.core.identity.ID) */ public IContainer getContainer(ID containerID) { if (containerID == null) return null; synchronized (containers) { ContainerEntry entry = (ContainerEntry) containers.get(containerID); if (entry == null) return null; return entry.getContainer(); } } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerManager#hasContainer(org.eclipse.ecf.core.identity.ID) */ public boolean hasContainer(ID containerID) { Assert.isNotNull(containerID); synchronized (containers) { return containers.containsKey(containerID); } } /* (non-Javadoc) * @see org.eclipse.ecf.core.IContainerManager#addListener(org.eclipse.ecf.core.IContainerManagerListener) */ public boolean addListener(IContainerManagerListener listener) { Assert.isNotNull(listener); synchronized (managerListeners) { return managerListeners.add(listener); } } /* (non-Javadoc) * @see org.eclipse.ecf.core.IContainerManager#removeListener(org.eclipse.ecf.core.IContainerManagerListener) */ public boolean removeListener(IContainerManagerListener listener) { Assert.isNotNull(listener); synchronized (managerListeners) { return managerListeners.remove(listener); } } public IContainer addContainer(IContainer container, ContainerTypeDescription typeDescription) { Assert.isNotNull(container); Assert.isNotNull(typeDescription); ID containerID = container.getID(); Assert.isNotNull(containerID, "Container ID cannot be null"); //$NON-NLS-1$ ContainerEntry result = null; synchronized (containers) { result = (ContainerEntry) containers.put(containerID, new ContainerEntry(container, typeDescription)); } if (result == null) fireContainerAdded(container); return container; } /** * @param result */ private void fireContainerAdded(IContainer result) { List toNotify = null; synchronized (managerListeners) { toNotify = new ArrayList(managerListeners); } for (Iterator i = toNotify.iterator(); i.hasNext();) { IContainerManagerListener cml = (IContainerManagerListener) i.next(); cml.containerAdded(result); } } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainerManager#removeContainer(org.eclipse.ecf.core.IContainer) */ public IContainer removeContainer(IContainer container) { Assert.isNotNull(container); ID containerID = container.getID(); if (containerID == null) return null; return removeContainer(containerID); } public IContainer removeContainer(ID containerID) { Assert.isNotNull(containerID); ContainerEntry result = null; synchronized (containers) { result = (ContainerEntry) containers.remove(containerID); } IContainer resultContainer = null; if (result != null) { resultContainer = result.getContainer(); fireContainerRemoved(resultContainer); } return resultContainer; } /** * @param result */ private void fireContainerRemoved(IContainer result) { List toNotify = null; synchronized (managerListeners) { toNotify = new ArrayList(managerListeners); } for (Iterator i = toNotify.iterator(); i.hasNext();) { IContainerManagerListener cml = (IContainerManagerListener) i.next(); cml.containerRemoved(result); } } public ContainerTypeDescription getContainerTypeDescription(ID containerID) { if (containerID == null) return null; synchronized (containers) { ContainerEntry entry = (ContainerEntry) containers.get(containerID); if (entry == null) return null; return entry.getContainerTypeDescription(); } } public IContainerFactory getContainerFactory() { return this; } public void removeAllContainers() { synchronized (containers) { for (Iterator i = containers.keySet().iterator(); i.hasNext();) { ID key = (ID) i.next(); ContainerEntry entry = (ContainerEntry) containers.get(key); i.remove(); fireContainerRemoved(entry.getContainer()); } } } /** * @since 3.1 */ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, ID containerID, Map parameters) throws ContainerCreateException { if (containerID == null) return createContainer(containerTypeDescription, parameters); if (parameters == null) return createContainer(containerTypeDescription, containerID); return createContainer(containerTypeDescription, new Object[] {containerID, parameters}); } /** * @since 3.1 */ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, String containerId, Map parameters) throws ContainerCreateException { if (containerId == null) return createContainer(containerTypeDescription, parameters); if (parameters == null) return createContainer(containerTypeDescription, containerId); return createContainer(containerTypeDescription, new Object[] {containerId, parameters}); } /** * @since 3.1 */ public IContainer createContainer(String containerTypeDescriptionName, ID containerID, Map parameters) throws ContainerCreateException { return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), containerID, parameters); } /** * @since 3.1 */ public IContainer createContainer(String containerTypeDescriptionName, String containerId, Map parameters) throws ContainerCreateException { return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), containerId, parameters); } /** * @since 3.1 */ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, Map parameters) throws ContainerCreateException { if (parameters == null) return createContainer(containerTypeDescription); return createContainer(containerTypeDescription, new Object[] {parameters}); } /** * @since 3.1 */ public IContainer createContainer(String containerTypeDescriptionName, Map parameters) throws ContainerCreateException { if (parameters == null) return createContainer(containerTypeDescriptionName); return createContainer(containerTypeDescriptionName, new Object[] {parameters}); } }