/* * Copyright 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.template.soy.base.internal; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; import com.google.common.io.CharSource; import com.google.common.io.Files; import com.google.common.io.Resources; import com.google.template.soy.base.SourceLocation; import com.google.template.soy.error.SoyCompilationException; import com.google.template.soy.error.SoyError; import com.google.template.soy.error.SoyErrorKind; import java.io.File; import java.io.IOException; import java.io.Reader; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; /** * Record for one input Soy file. * * <p>Important: Do not use outside of Soy code (treat as superpackage-private). * * <p>TODO(lukes): This should either be a subtype of CharSource or hold a CharSource * */ public interface SoyFileSupplier { /** * An opaque identifier that can be compared for equality with other versions from the same * resource. * * <p>Instances are not {@code Comparable} since a version is not necessarily monotonic ; e.g. a * cryptographically strong hash function produces a more reliable version identifier than a * time-stamp but not one that can be said to be newer or older than any other version. */ interface Version { /** * Compares to versions that are equivalent. Meaningless if applied to versions from a different * resource. */ @Override boolean equals(Object o); /** A version for stable resources : resources that don't change over the life of a JVM. */ Version STABLE_VERSION = new Version() {}; } /** * Returns a {@link Reader} for the Soy file content. * * @throws IOException If there is an error opening the input. */ Reader open() throws IOException; /** True if the underlying resource has changed since the given version. */ boolean hasChangedSince(Version version); /** Returns the kind of this input Soy file. */ SoyFileKind getSoyFileKind(); /** Returns the path to the Soy file, used for as a unique map/set key and for messages. */ String getFilePath(); /** Returns the version of the Soy file read. */ Version getVersion(); /** * Container for factory methods for {@link SoyFileSupplier}s. * * <p>Important: Do not use outside of Soy code (treat as superpackage-private). */ final class Factory { private static final SoyErrorKind FILE_URL_SYNTAX = SoyErrorKind.of("file URL has invalid syntax: ''{0}''"); /** * Creates a new {@code SoyFileSupplier} given a {@code CharSource} for the file content, as * well as the desired file path for messages. * * @param contentSource Source for the Soy file content. * @param soyFileKind The kind of this input Soy file. * @param filePath The path to the Soy file, used for as a unique map/set key and for messages. */ public static SoyFileSupplier create( CharSource contentSource, SoyFileKind soyFileKind, String filePath) { return new StableSoyFileSupplier(contentSource, soyFileKind, filePath); } /** * Creates a new {@code SoyFileSupplier} given a {@code File}. * * @param inputFile The Soy file. * @param soyFileKind The kind of this input Soy file. */ public static SoyFileSupplier create(File inputFile, SoyFileKind soyFileKind) { return create(Files.asCharSource(inputFile, UTF_8), soyFileKind, inputFile.getPath()); } /** * Creates a new {@code SoyFileSupplier} given a resource {@code URL}, as well as the desired * file path for messages. * * @param inputFileUrl The URL of the Soy file. * @param soyFileKind The kind of this input Soy file. * @param filePath The path to the Soy file, used for as a unique map/set key and for messages. */ public static SoyFileSupplier create( URL inputFileUrl, SoyFileKind soyFileKind, String filePath) { if (inputFileUrl.getProtocol().equals("file")) { // If the URL corresponds to a local file (such as a resource during local development), // open it up as a volatile file, so we can account for changes to the file. URI inputFileUri; try { inputFileUri = inputFileUrl.toURI(); } catch (URISyntaxException ex) { SoyError e = SoyError.DEFAULT_FACTORY.create( new SourceLocation(inputFileUrl.toString()), FILE_URL_SYNTAX, inputFileUrl); SoyCompilationException sce = new SoyCompilationException(ImmutableList.of(e)); sce.initCause(ex); throw sce; } return new VolatileSoyFileSupplier(new File(inputFileUri), soyFileKind); } else { return create(Resources.asCharSource(inputFileUrl, UTF_8), soyFileKind, filePath); } } /** * Creates a new {@code SoyFileSupplier} given a resource {@code URL}. * * <p>Important: This function assumes that the desired file path is returned by {@code * inputFileUrl.toString()}. If this is not the case, please use {@link #create(java.net.URL, * SoyFileKind, String)} instead. * * @see #create(java.net.URL, SoyFileKind, String) * @param inputFileUrl The URL of the Soy file. * @param soyFileKind The kind of this input Soy file. */ public static SoyFileSupplier create(URL inputFileUrl, SoyFileKind soyFileKind) { return create(inputFileUrl, soyFileKind, inputFileUrl.toString()); } /** * Creates a new {@code SoyFileSupplier} given the file content provided as a string, as well as * the desired file path for messages. * * @param content The Soy file content. * @param soyFileKind The kind of this input Soy file. * @param filePath The path to the Soy file, used for as a unique map/set key and for messages. */ public static SoyFileSupplier create( CharSequence content, SoyFileKind soyFileKind, String filePath) { return create(CharSource.wrap(content), soyFileKind, filePath); } private Factory() { // Not instantiable. } } }