/*******************************************************************************
* Copyright (c) 2009-2015 CWI
* 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:
* * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
* * Paul Klint - Paul.Klint@cwi.nl - CWI
* * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.uri;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
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.AssertionFailedException;
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.rascalmpl.eclipse.Activator;
import io.usethesource.vallang.ISourceLocation;
import org.rascalmpl.values.ValueFactoryFactory;
public class ProjectURIResolver implements ISourceLocationInputOutput, IURIResourceResolver {
public static ISourceLocation constructProjectURI(IProject project, IPath path){
return constructProjectURI(project.getName(), path);
}
private static ISourceLocation constructProjectURI(String project, IPath path){
try{
return ValueFactoryFactory.getValueFactory().sourceLocation("project", project, "/" + path.toString());
}
catch(URISyntaxException usex){
throw new BadURIException(usex);
}
}
public static ISourceLocation constructProjectURI(IPath workspaceAbsolutePath){
String projectName = workspaceAbsolutePath.segment(0);
IPath projectAbsolutePath = workspaceAbsolutePath.removeFirstSegments(1);
return constructProjectURI(projectName, projectAbsolutePath);
}
@Override
public InputStream getInputStream(ISourceLocation uri) throws IOException {
try {
return resolveFile(uri).getContents();
} catch (CoreException e) {
Throwable cause = e.getCause();
if (cause instanceof IOException) {
throw (IOException) cause;
}
throw new IOException(e.getMessage());
}
}
public IFile resolveFile(ISourceLocation uri) throws IOException, MalformedURLException {
if ("".equals(uri.getAuthority())) {
throw new IOException("location needs a project name as authority" + uri);
}
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(uri.getAuthority());
if (project == null) {
throw new IOException("project " + uri.getAuthority() + " does not exist");
}
return project.getFile(new Path(uri.getPath()));
}
private IContainer resolveFolder(ISourceLocation uri) throws IOException, MalformedURLException {
if ("".equals(uri.getAuthority())) {
throw new IOException("location needs a project name as authority" + uri);
}
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(uri.getAuthority());
if (project == null) {
throw new IOException("project " + uri.getAuthority() + " does not exist");
}
if (uri.getPath().isEmpty() || uri.getPath().equals("/")) {
return project;
}
else {
return project.getFolder(uri.getPath());
}
}
private IResource resolve(ISourceLocation uri) throws IOException, MalformedURLException {
if ("".equals(uri.getAuthority())) {
throw new IOException("location needs a project name as authority" + uri);
}
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(uri.getAuthority());
if (project == null || !project.exists()) {
throw new IOException("project " + uri.getAuthority() + " does not exist.");
}
if (!project.isOpen()) {
throw new IOException("project " + uri.getAuthority() + " is closed.");
}
if (uri.getPath().isEmpty() || uri.getPath().equals("/")) {
return project;
}
if(isDirectory(uri)){
return project.getFolder(uri.getPath());
}
if(isFile(uri)){
return project.getFile(uri.getPath());
}
throw new IOException(uri+" refers to a resource that does not exist.");
}
public OutputStream getOutputStream(final ISourceLocation uri, boolean append) throws IOException {
try {
IFile file = resolveFile(uri);
// this is necessary to also flush possible parent folders to disk first
if (!file.exists()) {
file.create(new ByteArrayInputStream(new byte[0]), true, new NullProgressMonitor());
}
// if the above is not done, then the parent folder does not exist.
return new FileOutputStream(file.getRawLocation().toOSString(), append) {
@Override
public void close() throws IOException {
super.close();
try {
file.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
} catch (CoreException e) {
Activator.getInstance().logException("could not refresh " + uri, e);
}
}
};
}
catch (CoreException e) {
throw new IOException(e);
}
}
public String scheme() {
return "project";
}
@Override
public boolean exists(ISourceLocation uri) {
try {
return resolve(uri).exists();
} catch (MalformedURLException e) {
return false;
} catch (IOException e) {
return false;
} catch (AssertionFailedException e) {
return false;
}
}
@Override
public boolean isDirectory(ISourceLocation uri) {
try {
return resolveFolder(uri).exists();
} catch (MalformedURLException e) {
return false;
} catch (IOException e) {
return false;
}
}
public boolean isFile(ISourceLocation uri) {
try {
return resolveFile(uri).exists();
} catch (MalformedURLException e) {
return false;
} catch (IOException e) {
return false;
}
}
@Override
public long lastModified(ISourceLocation uri) {
try {
return resolve(uri).getLocalTimeStamp();
} catch (MalformedURLException e) {
return 0L;
} catch (IOException e) {
return 0L;
}
}
@Override
public String[] list(ISourceLocation uri) throws IOException {
try {
IContainer folder = resolveFolder(uri);
IResource[] members = folder.members();
String[] result = new String[members.length];
for (int i = 0; i < members.length; i++) {
result[i] = members[i].getName();
}
return result;
} catch (CoreException e) {
throw new IOException(e);
}
}
@Override
public void remove(ISourceLocation uri) throws IOException {
try {
resolve(uri).delete(true, new NullProgressMonitor());
} catch (CoreException e) {
throw new IOException("could not remove file", e);
}
}
@Override
public void mkDirectory(ISourceLocation uri) throws IOException {
IContainer resolved = resolveFolder(uri);
NullProgressMonitor pm = new NullProgressMonitor();
if (!resolved.exists()) {
try {
if (resolved instanceof IFolder) {
((IFolder) resolved).create(false, true, pm);
resolved.refreshLocal(IResource.DEPTH_ZERO, pm);
}
else if (resolved instanceof IProject) {
IProject project = (IProject) resolved;
project.create(pm);
project.open(pm);
}
return;
} catch (CoreException e) {
throw new IOException(e.getMessage(), e);
}
}
return;
}
@Override
public boolean supportsHost() {
return false;
}
@Override
public Charset getCharset(ISourceLocation uri) throws IOException {
IFile file;
try {
file = resolveFile(uri);
} catch (MalformedURLException e) {
return null;
}
if (file != null) {
try {
String charsetName = file.getCharset();
if (charsetName != null)
return Charset.forName(charsetName);
} catch (CoreException e) {
return null;
}
}
return null;
}
@Override
public IResource getResource(ISourceLocation uri) throws IOException {
return resolve(uri);
}
}