/** * Copyright (c) 2007 Borland Software Corporation * * 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: * bblajer - initial API and implementation */ package org.eclipse.gmf.internal.xpand; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.gmf.internal.xpand.build.WorkspaceResourceManager; import org.eclipse.gmf.internal.xpand.expression.SyntaxConstants; import org.eclipse.gmf.internal.xpand.migration.Activator; /** * Tracks template roots for a given project. */ public class RootManager { public static final IPath PROJECT_RELATIVE_PATH_TO_CONFIG_FILE = new Path(".xpand-root"); //$NON-NLS-1$ private final IFile myConfig; private List<RootDescription> myRoots; private List<IRootChangeListener> myListeners = new ArrayList<IRootChangeListener>(2); private RootDescription myFallbackRoot; private IProject myProject; public RootManager(IProject project) { myConfig = project.getFile(PROJECT_RELATIVE_PATH_TO_CONFIG_FILE); myProject = project; } public void addRootChangeListener(IRootChangeListener l) { if (l != null && !myListeners.contains(l)) { myListeners.add(l); } } public void removeRootChangeListener(IRootChangeListener l) { myListeners.remove(l); } public void rootsChanged() { myRoots = null; for (IRootChangeListener next : myListeners) { next.rootsChanged(this); } } protected IProject getProject() { return myConfig.getProject(); } public boolean isTemplateRoot(IContainer container) { for (Iterator<RootDescription> it = getRoots().iterator(); it.hasNext();) { RootDescription nextDescription = it.next(); if (nextDescription.contains(container) && nextDescription.getRelativePath(container).isEmpty()) { return true; } } return false; } public List<IFolder> getXpandRootFolders() { List<IFolder> rootFolders = new ArrayList<IFolder>(); for (RootDescription rootDescription : getRoots()) { IPath mainIPath = rootDescription.getMainIPath(); if (mainIPath == null) { continue; } IFolder rootFolder = null; if (mainIPath.isAbsolute()) { assert mainIPath.segmentCount() > 1; //Try workspace-relative first. IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(mainIPath.segment(0)); if (project.isAccessible() && project.equals(myProject)) { rootFolder = myProject.getFolder(mainIPath.removeFirstSegments(1)); } } else { rootFolder = myProject.getFolder(mainIPath); } if (rootFolder != null && rootFolder.exists()) { rootFolders.add(rootFolder); } } return rootFolders; } public String getTemplateFullName(IFile file) { IPath relativePath = null; for (Iterator<RootDescription> it = getRoots().iterator(); it.hasNext() && relativePath == null;) { RootDescription nextDescription = it.next(); if (nextDescription.contains(file)) { relativePath = nextDescription.getRelativePath(file); } } if (relativePath == null) { relativePath = getFallbackRoot().getRelativePath(file); } if (relativePath == null) { return null; } relativePath = relativePath.removeFileExtension(); String templateFullName = relativePath.toString(); if (templateFullName.startsWith("/")) { templateFullName = templateFullName.substring(1); } if (templateFullName.endsWith("/")) { templateFullName = templateFullName.substring(0, templateFullName.length() - 1); } return templateFullName.replace("/", SyntaxConstants.NS_DELIM); } public WorkspaceResourceManager getResourceManager(IFile file) { for (RootDescription nextDescription : getRoots()) { if (nextDescription.contains(file)) { return nextDescription.getManager(); } } return getFallbackRoot().getManager(); } private RootDescription getFallbackRoot() { if (myFallbackRoot == null) { myFallbackRoot = new RootDescription(Collections.<IPath>singletonList(new Path(""))); } return myFallbackRoot; } private List<RootDescription> getRoots() { if (myRoots == null) { reloadRoots(); } return myRoots; } private void reloadRoots() { if (!myConfig.exists()) { myRoots = Collections.singletonList(new RootDescription(DEFAULT_ROOTS)); return; } final ArrayList<RootDescription> read = new ArrayList<RootDescription>(); BufferedReader in = null; try { in = new BufferedReader(new InputStreamReader(myConfig.getContents(), myConfig.getCharset())); String line; while((line = in.readLine()) != null) { line = line.trim(); if (line.length() > 0 && line.charAt(0) != '#') { String[] split = line.split(","); ArrayList<IPath> nextPaths = new ArrayList<IPath>(split.length); for (String nextPath : split) { nextPath = nextPath.trim(); if (nextPath.length() > 0) { IPath toAdd = new Path(nextPath); //Absolute paths specify resources relative to workbench and/or if (toAdd.isAbsolute() && toAdd.segmentCount() < 2) { continue; } nextPaths.add(toAdd); } } if (nextPaths.size() > 0) { read.add(new RootDescription(nextPaths)); } } } } catch (CoreException ex) { // IGNORE } catch (IOException ex) { // IGNORE } finally { if (in != null) { try { in.close(); } catch (IOException ex) { /* IGNORE */ } } } myRoots = read; } public Set<IProject> getReferencedProjects() { Set<IProject> result = new LinkedHashSet<IProject>(); for (RootDescription nextDescription : getRoots()) { for (IPath next : nextDescription.getRoots()) { if (next.isAbsolute() && next.segmentCount() > 1) { IProject candidate = ResourcesPlugin.getWorkspace().getRoot().getProject(next.segment(0)); if (candidate.isAccessible()) { result.add(candidate); } } } } return result; } public boolean containsProject(IPath projectPath) { if (myRoots == null) { return false; } for (RootDescription nextRoots : myRoots) { for (IPath next : nextRoots.getRoots()) { if (next.isAbsolute() && projectPath.isPrefixOf(next)) { return true; } } } return false; } public List<IPath> getMigratedXpandRootEntry(IContainer rootFolder, IFolder templatesOutputFolder) { assert rootFolder instanceof IFolder || rootFolder instanceof IProject; if (rootFolder instanceof IFolder) { RootDescription rootDescription = getRootDescription((IFolder) rootFolder); assert rootDescription != null; List<IPath> newRoots = new ArrayList<IPath>(rootDescription.getOriginalRoots()); for (int i = 0; i < newRoots.size(); i++) { if (i == 0) { newRoots.set(0, templatesOutputFolder.getProjectRelativePath()); } else { newRoots.set(i, Activator.getDefault().getLegacyTemplateRootRegistry().getMigratedRoot(newRoots.get(i))); } } return newRoots; } else { return Collections.singletonList(templatesOutputFolder.getProjectRelativePath()); } } private RootDescription getRootDescription(IFolder rootFolder) { for (RootDescription rootDescription : getRoots()) { IPath mainIPath = rootDescription.getMainIPath(); if (mainIPath == null) { continue; } IFolder descriptionRootFolder = null; if (mainIPath.isAbsolute()) { assert mainIPath.segmentCount() > 1; // Try workspace-relative first. IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(mainIPath.segment(0)); if (project.isAccessible() && project.equals(myProject)) { descriptionRootFolder = myProject.getFolder(mainIPath.removeFirstSegments(1)); } } else { descriptionRootFolder = myProject.getFolder(mainIPath); } if (descriptionRootFolder != null && descriptionRootFolder.exists() && descriptionRootFolder.equals(rootFolder)) { return rootDescription; } } return null; } private static final List<IPath> DEFAULT_ROOTS = Collections.<IPath>singletonList(new Path("templates")); //$NON-NLS-1$ public interface IRootChangeListener { public void rootsChanged(RootManager rootManager); } public class RootDescription { private final List<IPath> myOriginalRoots; private final List<IPath> myRoots; private WorkspaceResourceManager myManager; public RootDescription(List<IPath> roots) { assert roots.size() > 0; myOriginalRoots = roots; myRoots = new ArrayList<IPath>(roots.size()); for (IPath iPath : roots) { myRoots.add(Activator.getDefault().getLegacyTemplateRootRegistry().getActualRoot(iPath)); } } public List<IPath> getOriginalRoots() { return myOriginalRoots; } public List<IPath> getRoots() { return myRoots; } public WorkspaceResourceManager getManager() { if (myManager == null) { myManager = new WorkspaceResourceManager(getProject(), myRoots.toArray(new IPath[myRoots.size()])); } return myManager; } public boolean contains(IResource resource) { if (resource == null) { return false; } for (IPath nextRoot : myRoots) { if (nextRoot.isAbsolute()) { if (nextRoot.isPrefixOf(resource.getFullPath())) { return true; } } else { if (resource.getProject().equals(getProject()) && nextRoot.isPrefixOf(resource.getProjectRelativePath())) { return true; } } } return false; } public IPath getRelativePath(IResource resource) { for (IPath nextRoot : myRoots) { if (nextRoot.isAbsolute()) { IPath fullPath = resource.getFullPath(); if (nextRoot.isPrefixOf(fullPath)) { return fullPath.removeFirstSegments(nextRoot.segmentCount()); } } else { IPath projectRelativePath = resource.getProjectRelativePath(); if (resource.getProject().equals(getProject()) && nextRoot.isPrefixOf(projectRelativePath)) { return projectRelativePath.removeFirstSegments(nextRoot.segmentCount()); } } } return null; } public IPath getMainIPath() { return myRoots.get(0); } } }