| /********************************************************************** |
| * Copyright (c) 2003, 2011 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.wst.server.core.util; |
| |
| import java.util.*; |
| |
| import org.eclipse.core.resources.*; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.wst.server.core.IModule; |
| import org.eclipse.wst.server.core.internal.ModuleFactory; |
| import org.eclipse.wst.server.core.internal.ServerPlugin; |
| import org.eclipse.wst.server.core.internal.Trace; |
| import org.eclipse.wst.server.core.model.ModuleFactoryDelegate; |
| /** |
| * A helper class for defining a module factory that provides modules |
| * based on projects. |
| * |
| * @since 1.0 |
| */ |
| public abstract class ProjectModuleFactoryDelegate extends ModuleFactoryDelegate { |
| private Map<IProject, IModule[]> modules = new HashMap<IProject, IModule[]>(); |
| |
| /** |
| * Construct a new ProjectModuleFactoryDelegate. |
| */ |
| public ProjectModuleFactoryDelegate() { |
| super(); |
| } |
| |
| /** |
| * Cache modules that exist in the given project. |
| * |
| * @param project a project to cache |
| * @since 2.0 |
| */ |
| private final IModule[] cacheModules(IProject project) { |
| if (project == null || !project.isAccessible()) |
| return null; |
| |
| IModule[] m = null; |
| try { |
| m = modules.get(project); |
| if (m != null) |
| return m; |
| } catch (Exception e) { |
| // ignore |
| } |
| |
| try { |
| m = createModules(project); |
| if (m != null) { |
| modules.put(project, m); |
| return m; |
| } |
| } catch (Throwable t) { |
| if (Trace.SEVERE) { |
| Trace.trace(Trace.STRING_SEVERE, "Error creating module", t); |
| } |
| } |
| return new IModule[0]; |
| } |
| |
| /** |
| * Cache all existing modules. |
| */ |
| private final void cacheModules() { |
| try { |
| IProject[] projects = getWorkspaceRoot().getProjects(); |
| int size = projects.length; |
| for (int i = 0; i < size; i++) { |
| if (projects[i].isAccessible()) { |
| boolean cache = true; |
| try { |
| Object o = modules.get(projects[i]); |
| if (o != null) |
| cache = false; |
| } catch (Exception e) { |
| // ignore |
| } |
| |
| if (cache) { |
| try { |
| IModule[] modules2 = createModules(projects[i]); |
| if (modules2 != null) |
| modules.put(projects[i], modules2); |
| } catch (Throwable t) { |
| if (Trace.SEVERE) { |
| Trace.trace(Trace.STRING_SEVERE, "Error creating module for " + projects[i].getName(), |
| t); |
| } |
| } |
| } |
| } |
| } |
| } catch (Exception e) { |
| if (Trace.SEVERE) { |
| Trace.trace(Trace.STRING_SEVERE, "Error caching modules", e); |
| } |
| } |
| } |
| |
| /** |
| * Returns the workspace root. |
| * |
| * @return the workspace root |
| */ |
| private static IWorkspaceRoot getWorkspaceRoot() { |
| return ResourcesPlugin.getWorkspace().getRoot(); |
| } |
| |
| /* |
| * @see ModuleFactoryDelegate#getModules() |
| */ |
| public final IModule[] getModules() { |
| cacheModules(); |
| |
| List<IModule> list = new ArrayList<IModule>(); |
| Iterator iter = modules.values().iterator(); |
| while (iter.hasNext()) { |
| IModule[] m = (IModule[]) iter.next(); |
| if (m != null) |
| list.addAll(Arrays.asList(m)); |
| } |
| |
| IModule[] modules2 = new IModule[list.size()]; |
| list.toArray(modules2); |
| return modules2; |
| } |
| |
| /** |
| * Handle changes to a project. |
| * |
| * @param project a project |
| * @param delta a resource delta |
| */ |
| public final static void handleGlobalProjectChange(IProject project, IResourceDelta delta) { |
| ModuleFactory[] factories = ServerPlugin.getModuleFactories(); |
| int size = factories.length; |
| for (int i = 0; i < size; i++) { |
| if (factories[i].delegate != null && factories[i].delegate instanceof ProjectModuleFactoryDelegate) { |
| ProjectModuleFactoryDelegate pmfd = (ProjectModuleFactoryDelegate) factories[i].delegate; |
| if (pmfd.deltaAffectsModules(delta)) { |
| pmfd.clearCache(project); |
| pmfd.clearCache(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Returns <code>true</code> if the delta may have changed modules, |
| * and <code>false</code> otherwise. |
| * |
| * @param delta a resource delta |
| * @return <code>true</code> if the delta may have changed modules, |
| * and <code>false</code> otherwise |
| */ |
| private final boolean deltaAffectsModules(IResourceDelta delta) { |
| final boolean[] b = new boolean[1]; |
| |
| final IPath[] listenerPaths = getListenerPaths(); |
| if (listenerPaths == null || listenerPaths.length == 0) |
| return false; |
| final int size = listenerPaths.length; |
| |
| try { |
| delta.accept(new IResourceDeltaVisitor() { |
| public boolean visit(IResourceDelta delta2) throws CoreException { |
| if (b[0]) |
| return false; |
| //Trace.trace(Trace.FINEST, delta2.getResource() + " " + delta2.getKind() + " " + delta2.getFlags()); |
| boolean ok = false; |
| IPath path = delta2.getProjectRelativePath(); |
| for (int i = 0; i < size; i++) { |
| if (listenerPaths[i].equals(path)) { |
| b[0] = true; |
| return false; |
| } else if (path.isPrefixOf(listenerPaths[i])) { |
| ok = true; |
| } |
| } |
| return ok; |
| } |
| }); |
| } catch (Exception e) { |
| // ignore |
| } |
| //Trace.trace(Trace.FINEST, "Delta contains change: " + t.b); |
| return b[0]; |
| } |
| |
| /** |
| * Clear cached metadata. |
| * |
| * @deprecated use {@link #clearCache(IProject)} instead |
| */ |
| protected void clearCache() { |
| // ignore |
| } |
| |
| /** |
| * Clear cached metadata. |
| * |
| * @since 2.0 |
| */ |
| protected void clearCache(IProject project) { |
| modules = new HashMap<IProject, IModule[]>(); |
| } |
| |
| /** |
| * Creates the module for a given project. |
| * |
| * @param project a project to create modules for |
| * @return a module, or <code>null</code> if there was no module in the project |
| * @see #createModules(IProject) |
| * @deprecated Use createModules(IProject) instead, which supports multiple modules |
| * per project |
| */ |
| protected IModule createModule(IProject project) { |
| return null; |
| } |
| |
| /** |
| * Creates the modules that are contained within a given project. |
| * |
| * @param project a project to create modules for |
| * @return a possibly-empty array of modules |
| */ |
| protected IModule[] createModules(IProject project) { |
| IModule module = createModule(project); |
| if (module == null) |
| return new IModule[0]; |
| |
| return new IModule[] { module }; |
| } |
| |
| /** |
| * Returns the list of resources that the module should listen to |
| * for state changes. The paths should be project relative paths. |
| * Subclasses can override this method to provide the paths. |
| * |
| * @return a possibly empty array of paths |
| */ |
| protected IPath[] getListenerPaths() { |
| return null; |
| } |
| |
| /* |
| * @see ModuleFactoryDelegate#getModules(IProject) |
| * @since 2.0 |
| */ |
| public IModule[] getModules(IProject project) { |
| return cacheModules(project); |
| } |
| |
| /* |
| * @see ModuleFactoryDelegate#findModule(String) |
| * @since 2.0 |
| */ |
| public IModule findModule(String id) { |
| try { |
| IPath pathToProject = new Path(null, id); |
| if (pathToProject.segmentCount() == 1) { |
| // only look for projects which means there should only be 1 segment in the path |
| IProject project = getWorkspaceRoot().getProject(id); |
| if (project != null) { |
| IModule[] m = cacheModules(project); |
| if (m != null) { |
| int size = m.length; |
| for (int i = 0; i < size; i++) { |
| String id2 = m[i].getId(); |
| int index = id2.indexOf(":"); |
| if (index >= 0) |
| id2 = id2.substring(index + 1); |
| |
| if (id.equals(id2)) |
| return m[i]; |
| } |
| } |
| } |
| } |
| } catch (Exception e) { |
| if (Trace.FINER) { |
| Trace.trace(Trace.STRING_FINER, "Could not find " + id + ". Reverting to default behaviour", e); |
| } |
| } |
| |
| // otherwise default to searching all modules |
| return super.findModule(id); |
| } |
| } |