/** * Copyright (c) 2010, Cloudsmith Inc. * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the copyright holder * listed above, as the Initial Contributor under such license. The text of * such license is available at www.eclipse.org. */ package org.cloudsmith.geppetto.pp.dsl.ui.linked; 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.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.emf.common.util.WrappedException; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.PlatformUI; /** * Helper class for dealing with external files in the ExtLinkedXtextEditor. * This class is responsible for managing the linked files - obtaining a link, unlinking it etc. * TODO: This class is specific to pp in a few places (file extension, name of project for links, * use of UTF-8), but is otherwise generic. */ public class ExtLinkedFileHelper { // TODO: Should be configurable public static final String AUTOLINK_PROJECT_NAME = "Geppetto.AutoFileSystemLinked"; // TODO: Should be configurable public static final String ENCODING_UTF8 = "utf-8"; private static void createLink(IProject project, IFile linkFile, java.net.URI uri) throws CoreException { IPath path = linkFile.getFullPath(); IPath folders = path.removeLastSegments(1).removeFirstSegments(1); IPath checkPath = Path.ROOT; int segmentCount = folders.segmentCount(); for(int i = 0; i < segmentCount; i++) { checkPath = checkPath.addTrailingSeparator().append(folders.segment(i)); IFolder folder = project.getFolder(checkPath); if(!folder.exists()) folder.create(true, true, null); } linkFile.createLink(uri, IResource.ALLOW_MISSING_LOCAL, null); } private static int getFirstFreeUntitled(IProject project) throws CoreException { IFolder untitledFolder = project.getFolder("untitled"); if(!untitledFolder.exists()) { untitledFolder.create(true, true, new NullProgressMonitor()); return 0; } IResource[] resources = untitledFolder.members(); int result = resources.length > 0 ? 1 : 0; for(IResource r : resources) { // tied to format "untitled-n" int dash = r.getName().indexOf("-"); if(dash < 0) continue; int sequence = Integer.valueOf(r.getName().substring(dash + 1, r.getName().length() - 3)); result = sequence > result ? sequence : result; } return result + 1; } /** * Throws WrappedException - the URI must refer to an existing file! * * @param uri * @return */ public static IFile obtainLink(java.net.URI uri, boolean untitled) { try { IWorkspace ws = ResourcesPlugin.getWorkspace(); // get, or create project if non existing IProject project = ws.getRoot().getProject(AUTOLINK_PROJECT_NAME); boolean newProject = false; if(!project.exists()) { project.create(null); newProject = true; } if(!project.isOpen()) { project.open(null); // if project is hidden files can not be opened in all cases // TODO: Add reference to Xtext issue. project.setHidden(false); } if(newProject) project.setDefaultCharset(ENCODING_UTF8, new NullProgressMonitor()); IFile linkFile = null; if(untitled) { int firstFree = getFirstFreeUntitled(project); IFolder untitledFolder = project.getFolder("untitled"); String fileName = "untitled" + (firstFree > 1 ? "-" + Integer.toString(firstFree) : "") + ".b3"; linkFile = untitledFolder.getFile(fileName); } else { // path in project that is the same as the external file's path to avoid collision // without need to create new names linkFile = project.getFile(uri.getPath()); } if(linkFile.exists()) linkFile.refreshLocal(1, null); // don't know if needed (or should be avoided...) else { // create the link createLink(project, linkFile, uri); } return linkFile; } catch(CoreException e) { throw new WrappedException(e); } } public static void unlinkInput(IFileEditorInput input) { IFile file = input.getFile(); // only delete links if they are in the autolink project if(file.isLinked() && file.getProject().getName().equals(ExtLinkedFileHelper.AUTOLINK_PROJECT_NAME)) { try { // if the editor is disposed because workbench is shutting down, it is NOT a good // idea to delete the link if(PlatformUI.isWorkbenchRunning() && !PlatformUI.getWorkbench().isClosing()) file.delete(true, null); } catch(CoreException e) { // Nothing to do really, it will be recreated/refreshed later if ever used - some garbage may stay behind... // TODO: log the issue e.printStackTrace(); } } } }