blob: 29c7668cc514698c82e4f5b3f360c0d088c41b2b [file] [log] [blame]
/**
* 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);
}
}
}