| /* |
| * 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); |
| } |
| } |