/******************************************************************************* * Copyright (c) 2007, 2011 Spring IDE Developers * 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: * Spring IDE Developers - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.webflow.core.internal.model; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.springframework.ide.eclipse.core.SpringCoreUtils; import org.springframework.ide.eclipse.core.internal.model.resources.SpringResourceChangeListener; import org.springframework.ide.eclipse.core.model.IModelElement; import org.springframework.ide.eclipse.core.model.IModelElementVisitor; import org.springframework.ide.eclipse.webflow.core.internal.model.resources.WebflowResourceChangeListener; import org.springframework.ide.eclipse.webflow.core.internal.model.update.WebflowModelUpdater; import org.springframework.ide.eclipse.webflow.core.model.IWebflowConfig; import org.springframework.ide.eclipse.webflow.core.model.IWebflowModel; import org.springframework.ide.eclipse.webflow.core.model.IWebflowModelListener; import org.springframework.ide.eclipse.webflow.core.model.IWebflowProject; /** * @author Christian Dupuis * @author Torsten Juergeleit */ public class WebflowModel extends AbstractModelElement implements IWebflowModel, IResourceChangeListener { private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock r = rwl.readLock(); private final Lock w = rwl.writeLock(); private List<IWebflowModelListener> listners = new ArrayList<IWebflowModelListener>(); private Map<IProject, IWebflowProject> projects = new ConcurrentHashMap<IProject, IWebflowProject>(); private IResourceChangeListener workspaceListener; public boolean hasProject(IProject project) { try { r.lock(); if (project != null && project.isAccessible() && projects.containsKey(project) && SpringCoreUtils.isSpringProject(project)) { return true; } } finally { r.unlock(); } return false; } public IWebflowProject getProject(IProject project) { try { r.lock(); if (hasProject(project)) { return (IWebflowProject) projects.get(project); } } finally { r.unlock(); } return new WebflowProject(project, this); } public IWebflowProject getProject(String name) { IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(name); return getProject(project); } public Collection<IWebflowProject> getProjects() { try { r.lock(); return projects.values(); } finally { r.unlock(); } } public IWebflowConfig getConfig(IFile configFile) { if (configFile != null) { IWebflowProject project = getProject(configFile.getProject()); if (project != null) { return project.getConfig(configFile); } } return null; } public void startup() { initialize(); // initializeModel(); IWorkspace workspace = ResourcesPlugin.getWorkspace(); workspace.addResourceChangeListener(this); // Add a ResourceChangeListener to the Eclipse Workspace workspaceListener = new WebflowResourceChangeListener(new WebflowResourceChangeEvents()); workspace.addResourceChangeListener(workspaceListener, SpringResourceChangeListener.LISTENER_FLAGS); } /* * private void initializeModel() { Job job = new Job("Initializing Spring Web Flow Model") { * * @Override protected IStatus run(IProgressMonitor monitor) { SubProgressMonitor subMonitor = new * SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN); TrueModelElementVisitor visitor = new * TrueModelElementVisitor(); accept(visitor, subMonitor); subMonitor.done(); return Status.OK_STATUS; } }; * job.setSystem(true); job.setPriority(Job.SHORT); // process asap job.schedule(); } */ public void shutdown() { initialize(); IWorkspace workspace = ResourcesPlugin.getWorkspace(); workspace.removeResourceChangeListener(this); // Remove the ResourceChangeListener from the Eclipse Workspace workspace.removeResourceChangeListener(workspaceListener); workspaceListener = null; // Remove all projects projects.clear(); } private void initialize() { try { w.lock(); this.projects.clear(); List projects = getBeansProjects(); if (!projects.isEmpty()) { Iterator iter = projects.iterator(); while (iter.hasNext()) { IProject project = (IProject) iter.next(); this.projects.put(project, new WebflowProject(project, this)); } } // Schedule model update WebflowModelUpdater.updateModel(getProjects()); } finally { w.unlock(); } } private static List<IProject> getBeansProjects() { List<IProject> springProjects = new ArrayList<IProject>(); IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (int i = 0; i < projects.length; i++) { IProject project = projects[i]; if (SpringCoreUtils.isSpringProject(project)) { springProjects.add(project); } } return springProjects; } public void registerModelChangeListener(IWebflowModelListener listener) { this.listners.add(listener); } public void removeModelChangeListener(IWebflowModelListener listener) { this.listners.remove(listener); } public void fireModelChangedEvent(IWebflowProject project) { for (IWebflowModelListener listener : this.listners) { listener.modelChanged(project); } } public void resourceChanged(IResourceChangeEvent event) { if (event.getSource() instanceof IWorkspace) { IResourceDelta delta = event.getDelta(); if (delta != null) { try { delta.accept(new WebflowProjectVisitor()); } catch (CoreException e) { } } } } private class WebflowProjectVisitor implements IResourceDeltaVisitor { public boolean visit(IResourceDelta delta) throws CoreException { IResource resource = delta.getResource(); switch (delta.getKind()) { case IResourceDelta.REMOVED: if (resource instanceof IFile) { IFile file = (IFile) resource; IWebflowProject wfProject = getProject(file.getProject()); if (wfProject != null && wfProject.getConfig((IFile) resource) != null) { IWebflowConfig config = wfProject.getConfig((IFile) resource); List<IWebflowConfig> configs = wfProject.getConfigs(); configs.remove(config); wfProject.setConfigs(configs); } return false; } break; } return true; } } public void removeProject(IProject project) { initialize(); fireModelChangedEvent(null); } public IModelElement[] getElementChildren() { Set<IModelElement> children = new HashSet<IModelElement>(); try { r.lock(); children.addAll(this.projects.values()); } finally { r.unlock(); } return children.toArray(new IModelElement[children.size()]); } public Object getAdapter(Class adapter) { return null; } public void accept(IModelElementVisitor visitor, IProgressMonitor monitor) { if (!monitor.isCanceled() && visitor.visit(this, monitor)) { for (IWebflowProject project : getProjects()) { project.accept(visitor, monitor); } } } public String getElementName() { return "WebflowModel"; } public IResource getElementResource() { return null; } public boolean isElementArchived() { return false; } }