package org.eclipse.jst.jsf.core.jsfappconfig.internal; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jst.jsf.common.internal.resource.ResourceSingletonObjectManager; import org.eclipse.jst.jsf.common.internal.strategy.AbstractTestableExtensibleDefaultProviderSelectionStrategy; import org.eclipse.jst.jsf.core.internal.JSFCorePlugin; /** * Responsible for producing and caching {@link IJSFAppConfigManager} instances by project. * <p> * This class will guarantee that he same instance of the {@link IJSFAppConfigManager} is returned for a given project * */ public class JSFAppConfigManagerFactory extends ResourceSingletonObjectManager<IJSFAppConfigManager, IProject>{ private static JSFAppConfigManagerFactory INSTANCE; //private constructor private JSFAppConfigManagerFactory(final IProject project) { super(project.getWorkspace()); } /** * Project property session key for testing. * Project value should hold the testable IJSFAppConfigManagerFactory instance or null * NOT API - for testing purposes */ public static final QualifiedName TESTABLE_FACTORY_SESSION_KEY = new QualifiedName(JSFCorePlugin.PLUGIN_ID, "JSFAppConfigManagerFactoryInstance"); //$NON-NLS-1$ /** * @param project * @return IJSFAppConfigManager */ public static IJSFAppConfigManager getJSFAppConfigManagerInstance(final IProject project) { try { return getJSFAppConfigManagerFactoryInstance(project).getInstance(project); } catch (ManagedObjectException e) { JSFCorePlugin.log(e, "Cannot create IJSFAppConfigManager for "+project.getName()+ " (1)"); //$NON-NLS-1$ //$NON-NLS-2$ } return null; } private synchronized static JSFAppConfigManagerFactory getJSFAppConfigManagerFactoryInstance(final IProject project) { if (INSTANCE == null) { INSTANCE = new JSFAppConfigManagerFactory(project); } return INSTANCE; } @Override protected IJSFAppConfigManager createNewInstance(final IProject project) { try { final IJSFAppConfigManagerFactory factory = getJSFAppConfigManagerFactoryProviderInstance(project); if (factory != null) { IJSFAppConfigManager jsfAppConfigMgr = factory.getInstance(project); // Make a call to ensure the underlying EMF models in // the providers (from the locators) are initialized // in this instance begin created. Helps avoid some // potential concurrency issues as models are created. jsfAppConfigMgr.getApplications(); return jsfAppConfigMgr; } } catch (ManagedObjectException e) { JSFCorePlugin.log(e, "Cannot create IJSFAppConfigManager for "+project.getName()+ " (2)"); //$NON-NLS-1$ //$NON-NLS-2$ } return null; } @Override protected IAdaptable unsafeRunBeforeGetInstance(IProject project) { super.unsafeRunBeforeGetInstance(project); if (!isInstance(project) && Job.getJobManager().currentRule() == null) { //Acquire a scheduling rule on the project so creation of a JSFAppConfigManager //does not attempt to acquire a rule which may be unavailable while still //synchronized on the ResourceSingletonObjectManager (JSFAppConfigManagerFactory) Job.getJobManager().beginRule(project, null); return new AdaptableBoolean(true); } return null; } @Override protected void unsafeRunAfterGetInstance(IProject project, IAdaptable stateObject) { super.unsafeRunAfterGetInstance(project, stateObject); if (stateObject instanceof AdaptableBoolean && ((AdaptableBoolean)stateObject).acquiredRule) { Job.getJobManager().endRule(project); } } private IJSFAppConfigManagerFactory getJSFAppConfigManagerFactoryProviderInstance(final IProject project) { final CompositeFactorySelectionStrategyProvider factoryProvider = new CompositeFactorySelectionStrategyProvider(); return factoryProvider != null ? factoryProvider.getFactoryToUse(project) : null; } private static class CompositeFactorySelectionStrategyProvider { public IJSFAppConfigManagerFactory getFactoryToUse(final IProject project) { final JSFAppConfigManagerProviderSelectionStrategy providerSelector = new JSFAppConfigManagerProviderSelectionStrategy(); addStrategies(providerSelector); final IJSFAppConfigManagerFactory provider = providerSelector.perform(project); if (provider != providerSelector.getNoResult()) { return provider; } return null; } private void addStrategies(final JSFAppConfigManagerProviderSelectionStrategy providerSelector) { providerSelector.addDefaultStrategy(new DefaultJSFAppConfigManagerProviderStrategy()); providerSelector.addExtensionStrategy(new ExtensionBasedJSFAppConfigManagerProviderStrategy()); providerSelector.addTestableStrategy(new TestableJSFAppConfigManagerProviderStrategy(TESTABLE_FACTORY_SESSION_KEY)); } } private static class JSFAppConfigManagerProviderSelectionStrategy extends AbstractTestableExtensibleDefaultProviderSelectionStrategy<IProject, IJSFAppConfigManagerFactory> { private static final IJSFAppConfigManagerFactory NO_RESULT = null; @Override public IJSFAppConfigManagerFactory getNoResult() { return NO_RESULT; } } private static class AdaptableBoolean implements IAdaptable { private final boolean acquiredRule; public AdaptableBoolean(boolean acquiredRule) { this.acquiredRule = acquiredRule; } public Object getAdapter(Class adapter) { return null; } } }