blob: 62671cb3a76297a46899386ebbd23052806f44dc [file] [log] [blame]
/*
* Copyright (c) 2006, 2008 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:
* Artem Tikhomirov (Borland)
* Boris Blajer (Borland) - support for composite resources
*/
package org.eclipse.gmf.internal.xpand.build;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import org.eclipse.core.resources.IFile;
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.core.runtime.Platform;
import org.eclipse.gmf.internal.xpand.expression.SyntaxConstants;
import org.eclipse.gmf.internal.xpand.migration.Activator;
import org.eclipse.gmf.internal.xpand.model.XpandResource;
import org.eclipse.gmf.internal.xpand.util.ParserException;
import org.eclipse.gmf.internal.xpand.util.ResourceManagerImpl;
import org.eclipse.gmf.internal.xpand.util.StreamConverter;
import org.eclipse.gmf.internal.xpand.xtend.ast.XtendResource;
import org.osgi.framework.Bundle;
// FIXME package-local?, refactor Activator.getResourceManager uses
public class WorkspaceResourceManager extends ResourceManagerImpl {
private final IProject contextProject;
private final IPath[] myConfiguredRoots;
public WorkspaceResourceManager(IProject context, IPath[] configuredRoots) {
this.contextProject = context;
myConfiguredRoots = configuredRoots;
}
public XtendResource loadXtendResource(IFile file) throws CoreException, IOException, ParserException {
String fullyQualifiedName;
if (file == null || (fullyQualifiedName = toFullyQualifiedName(file)) == null) {
return null;
}
// try file directly, to get IO/Parse exceptions, if any.
Reader r = new StreamConverter().toContentsReader(file);
loadXtendResources(new Reader[] { r }, fullyQualifiedName);
//
try {
return loadXtendThroughCache(fullyQualifiedName);
} catch (FileNotFoundException ex) {
return null; //Missing resource is an anticipated situation, not a error that should be handled
}
}
public XpandResource loadXpandResource(IFile file) throws CoreException, IOException, ParserException {
String fullyQualifiedName;
if (file == null || (fullyQualifiedName = toFullyQualifiedName(file)) == null) {
return null;
}
// try file directly, to get IO/Parse exceptions, if any.
Reader r = new StreamConverter().toContentsReader(file);
loadXpandResources(new Reader[] { r }, fullyQualifiedName);
//
fullyQualifiedName = getNonAspectsTemplateName(fullyQualifiedName);
try {
return loadXpandThroughCache(fullyQualifiedName);
} catch (FileNotFoundException ex) {
return null; //Missing resource is an anticipated situation, not a error that should be handled
}
}
@Override
protected void handleParserException(ParserException ex) {
// may get here only when some referenced template/xtend file is
// broken. Since it's expected to get compiled anyway (either prior
// to compilation of its use or afterwards), error messages should get
// into problems view sooner or later.
Activator.logWarn(ex.getClass().getSimpleName() + ":" + ex.getResourceName());
}
@Override
protected boolean shouldCache() {
// we don't cache workspace resources for now (for the sake of reducing
// underemined problems that may arise), although may do this later
return false;
}
public void forget(IFile resource) {
// implement when caching
}
public Reader[] resolveMultiple(String fqn, String ext) throws IOException {
IPath fp = new Path(fqn.replaceAll(SyntaxConstants.NS_DELIM, "/")).addFileExtension(ext);
IPath[] resolutions = getResolutions(fp);
ArrayList<Reader> result = new ArrayList<Reader>(resolutions.length);
for (IPath p : getResolutions(fp)) {
Reader nextReader = getReader(p);
if (nextReader != null) {
result.add(nextReader);
}
}
if (result.isEmpty()) {
throw new FileNotFoundException(fp.toString());
}
return result.toArray(new Reader[result.size()]);
}
private Reader getReader(IPath p) throws IOException {
if (p.isAbsolute()) {
assert p.segmentCount() > 1;
//Try workspace-relative first.
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(p.segment(0));
if (project.isAccessible()) {
return getWorkspaceFileReader(project, p.removeFirstSegments(1));
}
//Fallback to platform location
Bundle platformBundle = Platform.getBundle(p.segment(0));
if (platformBundle != null) {
URL url = platformBundle.getEntry(p.removeFirstSegments(1).toString());
if (url != null) {
InputStream is = url.openStream();
return new InputStreamReader(is, Charset.forName("ISO-8859-1")); //$NON-NLS-1$
}
}
} else {
return getWorkspaceFileReader(contextProject, p);
}
return null;
}
private Reader getWorkspaceFileReader(IProject project, IPath path) throws IOException {
IResource r = project.findMember(path);
if (r instanceof IFile) {
try {
return new StreamConverter().toContentsReader((IFile) r);
} catch (CoreException ex) {
IOException wrap = new IOException(ex.getStatus().getMessage());
wrap.initCause(ex);
throw wrap;
}
}
return null;
}
private IPath[] getResolutions(IPath p) {
IPath[] rv = new IPath[myConfiguredRoots.length];
for (int i = 0; i < myConfiguredRoots.length; i++) {
rv[i] = myConfiguredRoots[i].append(p);
}
return rv;
}
private String toFullyQualifiedName(IFile file) {
for (IPath nextRoot : myConfiguredRoots) {
if (!nextRoot.isAbsolute()) {
if (file.getProject().equals(contextProject) && nextRoot.isPrefixOf(file.getProjectRelativePath())) {
return toFullyQualifiedName(file.getProjectRelativePath().removeFirstSegments(nextRoot.segmentCount()));
}
} else {
if (nextRoot.isPrefixOf(file.getFullPath())) {
return toFullyQualifiedName(file.getFullPath().removeFirstSegments(nextRoot.segmentCount()));
}
}
}
return null;
}
private static String toFullyQualifiedName(IPath filePath) {
return filePath.removeFileExtension().toString().replace("/", SyntaxConstants.NS_DELIM);
}
}