| // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| package com.google.dart.compiler; |
| |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.Reader; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * A mock application source that uses resources bundled in the classpath, along with methods for |
| * remapping sources and modifying their timestamps. |
| */ |
| public class MockBundleLibrarySource extends UrlLibrarySource implements LibrarySource { |
| |
| private class NonexistentDartSource implements DartSource { |
| private final String relPath; |
| |
| public NonexistentDartSource(String relPath) { |
| this.relPath = relPath; |
| } |
| |
| @Override |
| public boolean exists() { |
| return false; |
| } |
| |
| @Override |
| public long getLastModified() { |
| return 0; |
| } |
| |
| @Override |
| public String getName() { |
| return relPath; |
| } |
| |
| @Override |
| public Reader getSourceReader() throws IOException { |
| throw new FileNotFoundException(); |
| } |
| |
| @Override |
| public String getUniqueIdentifier() { |
| return relPath; |
| } |
| |
| @Override |
| public URI getUri() { |
| try { |
| return new URI(relPath); |
| } catch (URISyntaxException e) { |
| throw new AssertionError(e.getMessage()); |
| } |
| } |
| |
| @Override |
| public LibrarySource getLibrary() { |
| return MockBundleLibrarySource.this; |
| } |
| |
| @Override |
| public String getRelativePath() { |
| return relPath; |
| } |
| } |
| |
| private final String basePath; |
| private final ClassLoader loader; |
| private final String libName; |
| |
| private final Map<String, MockBundleLibrarySource> imports = |
| new HashMap<String, MockBundleLibrarySource>(); |
| |
| /** |
| * Source remappings. Each key identifies the name of a source file that will be remapped to an |
| * alternate source file in {@link #getSourceFor(String)}. |
| */ |
| private final Map<String, String> sourceRemapping = new HashMap<String, String>(); |
| private final Set<String> sourceTimestamps = new HashSet<String>(); |
| |
| public MockBundleLibrarySource(ClassLoader loader, String basePath, String libName) |
| throws URISyntaxException { |
| this(loader, basePath, libName, libName); |
| } |
| |
| public MockBundleLibrarySource(ClassLoader loader, String basePath, String libName, |
| String altName) throws URISyntaxException { |
| super(loader.getResource(basePath + libName).toURI()); |
| this.loader = loader; |
| this.basePath = basePath; |
| this.libName = altName; |
| } |
| |
| @Override |
| public MockBundleLibrarySource getImportFor(String relPath) { |
| MockBundleLibrarySource libSrc = imports.get(relPath); |
| if (libSrc == null) { |
| try { |
| libSrc = new MockBundleLibrarySource(loader, basePath, relPath); |
| } catch (URISyntaxException e) { |
| throw new AssertionError(); |
| } |
| imports.put(relPath, libSrc); |
| } |
| return libSrc; |
| } |
| |
| @Override |
| public DartSource getSourceFor(final String relPath) { |
| String remap = sourceRemapping.get(relPath); |
| final boolean touched = sourceTimestamps.contains(relPath); |
| |
| String fullPath = basePath + ((remap != null) ? remap : relPath); |
| URI uri; |
| try { |
| URL url = loader.getResource(fullPath); |
| if (url == null) { |
| return new NonexistentDartSource(relPath); |
| } |
| |
| uri = url.toURI(); |
| } catch (URISyntaxException e) { |
| throw new AssertionError(); |
| } |
| |
| return new UrlDartSource(uri, relPath, this) { |
| @Override |
| public long getLastModified() { |
| if (touched) { |
| return new Date().getTime(); |
| } |
| return super.getLastModified(); |
| } |
| |
| @Override |
| public String getName() { |
| return relPath; |
| } |
| }; |
| } |
| |
| @Override |
| public String getName() { |
| return libName; |
| } |
| |
| /** |
| * Remaps the given source to an alternate. This allows testing of changes to source contents. |
| * Note that you'll still need to call {@link #touchSource(String)} to cause it to be recompiled. |
| */ |
| public void remapSource(String relPath, String remappedRelPath) { |
| sourceRemapping.put(relPath, remappedRelPath); |
| touchSource(relPath); |
| } |
| |
| /** |
| * Removes the given source. Any attempt to read it will result in an NPE. |
| */ |
| public void removeSource(String relPath) { |
| sourceRemapping.put(relPath, "does/not/exist"); |
| } |
| |
| /** |
| * Touches the given source file, forcing a recompile. |
| */ |
| public void touchSource(String relPath) { |
| sourceTimestamps.add(relPath); |
| } |
| |
| /** |
| * Clears all remappings and source timestamps. |
| */ |
| public void resetRemappings() { |
| sourceRemapping.clear(); |
| sourceTimestamps.clear(); |
| } |
| } |