package org.eclipse.jst.jsf.core.jsfappconfig.internal; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.EContentAdapter; import org.eclipse.jst.jsf.common.internal.managedobject.AbstractManagedObject; import org.eclipse.jst.jsf.core.internal.JSFCorePlugin; import org.eclipse.jst.jsf.core.jsfappconfig.IFacesConfigChangeListener; import org.eclipse.jst.jsf.core.jsfappconfig.IJSFAppConfigLocater; import org.eclipse.jst.jsf.core.jsfappconfig.IJSFAppConfigProvider; import org.eclipse.jst.jsf.core.jsfappconfig.IJSFAppConfigProvidersChangeListener; import org.eclipse.jst.jsf.core.jsfappconfig.JSFAppConfigProvidersChangeEvent; import org.eclipse.jst.jsf.core.jsfappconfig.JSFAppConfigUtils; import org.eclipse.jst.jsf.facesconfig.emf.ApplicationType; import org.eclipse.jst.jsf.facesconfig.emf.BehaviorType; import org.eclipse.jst.jsf.facesconfig.emf.ComponentType; import org.eclipse.jst.jsf.facesconfig.emf.ConverterType; import org.eclipse.jst.jsf.facesconfig.emf.ELResolverType; import org.eclipse.jst.jsf.facesconfig.emf.FacesConfigExtensionType; import org.eclipse.jst.jsf.facesconfig.emf.FacesConfigType; import org.eclipse.jst.jsf.facesconfig.emf.FactoryType; import org.eclipse.jst.jsf.facesconfig.emf.FromViewIdType; import org.eclipse.jst.jsf.facesconfig.emf.LifecycleType; import org.eclipse.jst.jsf.facesconfig.emf.ManagedBeanType; import org.eclipse.jst.jsf.facesconfig.emf.NavigationRuleType; import org.eclipse.jst.jsf.facesconfig.emf.PropertyResolverType; import org.eclipse.jst.jsf.facesconfig.emf.ReferencedBeanType; import org.eclipse.jst.jsf.facesconfig.emf.RenderKitType; import org.eclipse.jst.jsf.facesconfig.emf.ResourceBundleType; import org.eclipse.jst.jsf.facesconfig.emf.ValidatorType; import org.eclipse.jst.jsf.facesconfig.emf.VariableResolverType; /** * Abstract JSFAppConfigManager that implementers of {@link IJSFAppConfigManager} MUST * extend. * <p> * JSFAppConfigManager provides an entry point to an entire JSF application * configuration, which is defined in one or more application configuration * resource files. */ public abstract class AbstractJSFAppConfigManager extends AbstractManagedObject implements IJSFAppConfigManager { /** * The IProject * @deprecated - use getProject() */ protected IProject _project; /** * Collection of {@link IJSFAppConfigLocater} instances. */ protected List<IJSFAppConfigLocater> configLocaters; /** * Collection of {@link IJSFAppConfigProvidersChangeListener} instances. */ protected List<IJSFAppConfigProvidersChangeListener> configProvidersChangeListeners; /** * Map of application configuration model EMF classes to * {@link IFacesConfigChangeListener} instances. */ protected Map<Class, IFacesConfigChangeListener> facesConfigChangeListeners; /** * Single {@link FacesConfigChangeAdapter} instance. */ protected FacesConfigChangeAdapter facesConfigChangeAdapter; /** * Constructor * @param project */ public AbstractJSFAppConfigManager(final IProject project) { _project = project; initialize(); } public IProject getProject() { return _project; } /** * Initializes instance by: * <ul> * <li>creating facesConfigChangeListeners collection, </li> * <li>creating configProvidersChangeListeners collection, </li> * <li>creating and populating configLocaters collection, </li> * <li>invoking the startLocating() method on all configLocaters, </li> * </ul> */ protected void initialize() { //create collections facesConfigChangeListeners = new HashMap<Class, IFacesConfigChangeListener>(); configProvidersChangeListeners = new ArrayList<IJSFAppConfigProvidersChangeListener>(); configLocaters = new ArrayList<IJSFAppConfigLocater>(); //populate initial set of locaters populateConfigLocaters(); //instruct locaters to start locating startConfigLocaters(); } /** * Populates configLocaters using @link IJSFAppConfigLocater} implementations * from CompositeLocatorProviderStrategy */ protected void populateConfigLocaters() { final CompositeJSFAppConfigLocatorProviderStrategy clps = new CompositeJSFAppConfigLocatorProviderStrategy(this.getProject()); for (final IJSFAppConfigLocater locator : clps.getLocators()) { locator.setJSFAppConfigManager(this); configLocaters.add(locator); } } /** * Instructs set of {@link IJSFAppConfigLocater} instances to start * locating JSF application configuration resources. */ protected void startConfigLocaters() { for (final IJSFAppConfigLocater configLocater : configLocaters) { SafeRunner.run(new ISafeRunnable(){ public void handleException(Throwable e) { JSFCorePlugin.log("While starting config locator", e); //$NON-NLS-1$ } public void run() throws Exception { configLocater.startLocating(); } }); } } /** * Instructs set of {@link IJSFAppConfigLocater} instances to stop * locating JSF application configuration resources. */ protected void stopConfigLocaters() { for (final IJSFAppConfigLocater configLocater : configLocaters) { SafeRunner.run(new ISafeRunnable() { public void handleException(Throwable exception) { JSFCorePlugin.log("Stopping a config locator", exception); //$NON-NLS-1$ } public void run() throws Exception { configLocater.stopLocating(); configLocater.dispose(); } }); } } /** * Called to respond to a change in the IProject instance to which this * instance belongs. Changes the cached IProject instance, stops all config * locaters, starts all config locaters. * * @param newProject New IProject instance to which this manager belongs. * @deprecated - SHOULD NOT USE */ protected void changeProject(final IProject newProject) { _project = newProject; stopConfigLocaters(); startConfigLocaters(); } public boolean addJSFAppConfigProvidersChangeListener(final IJSFAppConfigProvidersChangeListener listener) { return configProvidersChangeListeners.add(listener); } public boolean removeJSFAppConfigProvidersChangeListener(final IJSFAppConfigProvidersChangeListener listener) { return configProvidersChangeListeners.remove(listener); } public void notifyJSFAppConfigProvidersChangeListeners(final IJSFAppConfigProvider configProvider, final int eventType) { final JSFAppConfigProvidersChangeEvent event = new JSFAppConfigProvidersChangeEvent(configProvider, eventType); for (final IJSFAppConfigProvidersChangeListener listener : configProvidersChangeListeners) { SafeRunner.run(new ISafeRunnable() { public void run() throws Exception { listener.changedJSFAppConfigProviders(event); } public void handleException(Throwable exception) { JSFCorePlugin.log("While notifying listeners", exception); //$NON-NLS-1$ } }); } } public Object addFacesConfigChangeListener(Class emfClass, IFacesConfigChangeListener listener) { /* * Get all models, which will ensure that each one has had a * FacesConfigChangeAdapter added to it (if the model is updateable). */ getFacesConfigModels(); return facesConfigChangeListeners.put(emfClass, listener); } public Object removeFacesConfigChangeListener(Class emfClass) { return facesConfigChangeListeners.remove(emfClass); } public void notifyFacesConfigChangeListeners(final Notification notification) { final Object emfFeature = notification.getFeature(); if (emfFeature instanceof EStructuralFeature) { final Class emfClass = ((EStructuralFeature)emfFeature).getEType().getInstanceClass(); final IFacesConfigChangeListener listener = facesConfigChangeListeners.get(emfClass); if (listener != null) { SafeRunner.run(new ISafeRunnable() { public void handleException(Throwable exception) { JSFCorePlugin.log("Problem while loading listeners", exception); //$NON-NLS-1$ } public void run() throws Exception { listener.notifyChanged(notification); } }); } } } /** * @return Set of {@link IJSFAppConfigProvider}s */ protected Set<IJSFAppConfigProvider> getJSFAppConfigProviders() { final Set<IJSFAppConfigProvider> allConfigProviders = new LinkedHashSet<IJSFAppConfigProvider>(); final Iterator itConfigLocaters = configLocaters.iterator(); while (itConfigLocaters.hasNext()) { final IJSFAppConfigLocater configLocater = (IJSFAppConfigLocater)itConfigLocaters.next(); SafeRunner.run(new ISafeRunnable() { public void run() throws Exception { allConfigProviders.addAll(configLocater.getJSFAppConfigProviders()); } public void handleException(Throwable exception) { JSFCorePlugin.log("While getting app config providers", exception); //$NON-NLS-1$ } }); } return allConfigProviders; } /** * Gets all {@link FacesConfigType} instances from all * {@link IJSFAppConfigProvider} instances. * * @return List of all {@link FacesConfigType} instances. */ protected List<FacesConfigType> getFacesConfigModels() { final List<FacesConfigType> facesConfigModels = new ArrayList<FacesConfigType>(); for(final IJSFAppConfigProvider configProvider : getJSFAppConfigProviders()) { SafeRunner.run(new ISafeRunnable() { public void handleException(Throwable exception) { //SafeRunner will log the exception } public void run() throws Exception { final FacesConfigType facesConfig = configProvider.getFacesConfigModel(); if (facesConfig != null) { facesConfigModels.add(facesConfig); } } }); } return facesConfigModels; } //----------------------- IManagedObject lifecycle methods ----------------------------// /** * Disposes of resources by: * <ul> * <li>removing a resource change listener to the workspace</li> * <li>removing instance as a session property of the IProject instance</li> * <li>invoking the stopLocating() method on all configLocaters</li> * <li>clearing the configLocaters collection</li> * <li>clearing the configProvidersChangeListeners collection</li> * <li>clearing the facesConfigChangeListeners collection</li> * </ul> */ @Override public void dispose() { //instruct locaters to stop locating stopConfigLocaters(); //clear collections configLocaters.clear(); configProvidersChangeListeners.clear(); facesConfigChangeListeners.clear(); } @Override public void destroy() { // no persistent data to cleanup. just call dispose. dispose(); } public void checkpoint() { // } //-------------------------------------------------------------------------------------------------// public List<ManagedBeanType> getManagedBeans() { final List<ManagedBeanType> allManagedBeans = new ArrayList<ManagedBeanType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList managedBeans = facesConfig.getManagedBean(); allManagedBeans.addAll(managedBeans); } return allManagedBeans; } public final List<String> getPropertyResolvers() { final List<String> allPropertyResolvers = new ArrayList<String>(); final List<ApplicationType> applications = getApplications(); for (final ApplicationType application : applications) { for (final Iterator it = application.getPropertyResolver().iterator(); it.hasNext();) { final PropertyResolverType propRes = (PropertyResolverType) it.next(); String propClass = propRes.getTextContent(); if (propClass != null) { propClass = propClass.trim(); if (!"".equals(propClass)) //$NON-NLS-1$ { allPropertyResolvers.add(propClass); } } } } return allPropertyResolvers; } public List<ValidatorType> getValidators() { final List<ValidatorType> allValidators = new ArrayList<ValidatorType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList validators = facesConfig.getValidator(); allValidators.addAll(validators); } return allValidators; } public final List<String> getVariableResolvers() { final List<String> allVariableResolvers = new ArrayList<String>(); final List<ApplicationType> applications = getApplications(); for ( final ApplicationType application : applications) { for (final Iterator it = application.getVariableResolver().iterator(); it.hasNext();) { final VariableResolverType varRes = (VariableResolverType) it.next(); String varClass = varRes.getTextContent(); if (varClass != null) { varClass = varClass.trim(); if (!"".equals(varClass)) //$NON-NLS-1$ { allVariableResolvers.add(varClass); } } } } return allVariableResolvers; } public final List<String> getELResolvers() { final List<String> allELResolvers = new ArrayList<String>(); final List<ApplicationType> applications = getApplications(); for (final ApplicationType application : applications) { for (final Iterator it = application.getELResolver().iterator(); it.hasNext();) { final ELResolverType varRes = (ELResolverType) it.next(); String varClass = varRes.getTextContent(); if (varClass != null) { varClass = varClass.trim(); if (!"".equals(varClass)) //$NON-NLS-1$ { allELResolvers.add(varClass); } } } } return allELResolvers; } public List<ConverterType> getConverters() { final List<ConverterType> allConverters = new ArrayList<ConverterType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList converters = facesConfig.getConverter(); allConverters.addAll(converters); } return allConverters; } public List<NavigationRuleType> getNavigationRules() { final List<NavigationRuleType> allNavigationRules = new ArrayList<NavigationRuleType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList navigationRules = facesConfig.getNavigationRule(); allNavigationRules.addAll(navigationRules); } return allNavigationRules; } public List<NavigationRuleType> getNavigationRulesForPage(final IFile pageFile) { final List<NavigationRuleType> navigationRulesForPage = new ArrayList<NavigationRuleType>(); final IPath pageFilePath = JSFAppConfigUtils.getWebContentFolderRelativePath(pageFile); if (pageFilePath != null) { String pageFileString = pageFilePath.toString(); if (!pageFileString.startsWith("/")) { //$NON-NLS-1$ pageFileString = "/" + pageFileString; //$NON-NLS-1$ } final List<NavigationRuleType> navigationRules = getNavigationRules(); for (final NavigationRuleType navigationRule : navigationRules) { FromViewIdType fromViewIdType = navigationRule.getFromViewId(); if (fromViewIdType != null) { final String fromViewId = fromViewIdType.getTextContent(); if (fromViewId != null && fromViewId.length() > 0) { if (!fromViewId.equals("*")) { //$NON-NLS-1$ if (fromViewId.equals(pageFileString)) { //exact match navigationRulesForPage.add(navigationRule); } else if (fromViewId.endsWith("*")) { //$NON-NLS-1$ final String prefixFromViewId = fromViewId.substring(0, fromViewId.length() - 1); if (pageFileString.startsWith(prefixFromViewId)) { //prefix match navigationRulesForPage.add(navigationRule); } } } else { //from-view-id == "*" - matches all pages navigationRulesForPage.add(navigationRule); } } } else { //no from-view-id element - matches all pages navigationRulesForPage.add(navigationRule); } } } return navigationRulesForPage; } public List<ApplicationType> getApplications() { final List<ApplicationType> allApplications = new ArrayList<ApplicationType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList applications = facesConfig.getApplication(); allApplications.addAll(applications); } return allApplications; } public List<FactoryType> getFactories() { final List<FactoryType> allFactories = new ArrayList<FactoryType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList factories = facesConfig.getFactory(); allFactories.addAll(factories); } return allFactories; } public List<ComponentType> getComponents() { final List<ComponentType> allComponents = new ArrayList<ComponentType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList components = facesConfig.getComponent(); allComponents.addAll(components); } return allComponents; } public List<ReferencedBeanType> getReferencedBeans() { final List<ReferencedBeanType> allReferencedBeans = new ArrayList<ReferencedBeanType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList referencedBeans = facesConfig.getReferencedBean(); allReferencedBeans.addAll(referencedBeans); } return allReferencedBeans; } public List<RenderKitType> getRenderKits() { final List<RenderKitType> allRenderKits = new ArrayList<RenderKitType> (); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList renderKits = facesConfig.getRenderKit(); allRenderKits.addAll(renderKits); } return allRenderKits; } public List<LifecycleType> getLifecycles() { final List<LifecycleType> allLifecycles = new ArrayList<LifecycleType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList lifecycles = facesConfig.getLifecycle(); allLifecycles.addAll(lifecycles); } return allLifecycles; } public List<ResourceBundleType> getResourceBundles() { final List<ResourceBundleType> allResourceBundles = new ArrayList<ResourceBundleType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { for (final Iterator applicationIt = facesConfig.getApplication().iterator(); applicationIt.hasNext();) { final ApplicationType appType = (ApplicationType) applicationIt.next(); allResourceBundles.addAll(appType.getResourceBundle()); } } return allResourceBundles; } public List<BehaviorType> getBehaviors() { final List<BehaviorType> allBehaviors = new ArrayList<BehaviorType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList behaviors = facesConfig.getBehavior(); allBehaviors.addAll(behaviors); } return allBehaviors; } public List<FacesConfigExtensionType> getFacesConfigExtensions() { final List<FacesConfigExtensionType> allFCExts = new ArrayList<FacesConfigExtensionType>(); for (final FacesConfigType facesConfig : getFacesConfigModels()) { final EList fcExts = facesConfig.getFacesConfigExtension(); allFCExts.addAll(fcExts); } return allFCExts; } public void addFacesConfigChangeAdapter(final FacesConfigType facesConfig) { if (facesConfig != null) { if (facesConfigChangeAdapter == null) { facesConfigChangeAdapter = new FacesConfigChangeAdapter(); } facesConfig.eAdapters().add(facesConfigChangeAdapter); } } public void removeFacesConfigChangeAdapter(final FacesConfigType facesConfig) { if (facesConfig != null && facesConfigChangeAdapter != null) { facesConfig.eAdapters().remove(facesConfigChangeAdapter); } } /** * FacesConfigChangeAdapter is an EMF adapter which provides a mechanism * for notification of changes to features in any application configuration * model for which {@link IFacesConfigChangeListener} instances have * registered an interest. * * @author Ian Trimble - Oracle */ class FacesConfigChangeAdapter extends EContentAdapter { /* * (non-Javadoc) * @see org.eclipse.emf.ecore.util.EContentAdapter#notifyChanged(org.eclipse.emf.common.notify.Notification) */ public void notifyChanged(final Notification notification) { super.notifyChanged(notification); notifyFacesConfigChangeListeners(notification); } } }