TemplateResources.java
/***************************************************************************
Copyright 2008 Emily Estes
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 net.metanotion.simpletemplate;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.metanotion.io.File;
import net.metanotion.io.FileSystem;
import net.metanotion.simpletemplate.interpreter.Load;
/** This class is a ResourceFactory that implements the scripting language described in the package
documentation and implemented in the net.metanotion.simpletemplate.interpreter package. When
loading files, this class assumes EVERY file is a template, so files that are not meant to be intepreted
as scripts should NOT be placed in the file system object passed to this ResourceFactory, instead
non-interpreted assets should be handled by a chained ResourceFactory like the StaticResources class. */
public final class TemplateResources implements ResourceFactory {
private static final Logger logger = LoggerFactory.getLogger(TemplateResources.class);
private static final String defMT = "text/html";
private final FileSystem<? extends File> fs;
private final Long maxExpire;
private final ResourceFactory parent;
private final boolean doETag;
private final String defaultMime;
private final Load loader;
/** Create a resource factory using the provided file system for scripts with all the default options.
@param fs The file system where scripts will be loaded from to be interpreted.
*/
public TemplateResources(final FileSystem<? extends File> fs) {
this(fs, false, null, NullTemplateHelper.INSTANCE, defMT);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param defMime If the file system does not provide a mime-type attribute for the file, use this to set the
content-type header.
*/
public TemplateResources(final FileSystem<? extends File> fs, final String defMime) {
this(fs, false, null, NullTemplateHelper.INSTANCE, defMime);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param doETag If true, create an ETag value and send an ETag header with the resource.
*/
public TemplateResources(final FileSystem<? extends File> fs, final boolean doETag) {
this(fs, doETag, null, NullTemplateHelper.INSTANCE, defMT);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param maxExpire If not-null set the max expiration date header to this value.
*/
public TemplateResources(final FileSystem<? extends File> fs, final Long maxExpire) {
this(fs, false, maxExpire, NullTemplateHelper.INSTANCE, defMT);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param parent When a resource cannot be loaded from the file system, delegate interpretation to this resource
factory.
*/
public TemplateResources(final FileSystem<? extends File> fs, final ResourceFactory parent) {
this(fs, false, null, parent, defMT);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param doETag If true, create an ETag value and send an ETag header with the resource.
@param parent When a resource cannot be loaded from the file system, delegate interpretation to this resource
factory.
*/
public TemplateResources(final FileSystem<? extends File> fs, final boolean doETag, final ResourceFactory parent) {
this(fs, doETag, null, parent, defMT);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param doETag If true, create an ETag value and send an ETag header with the resource.
@param maxExpire If not-null set the max expiration date header to this value.
*/
public TemplateResources(FileSystem<? extends File> fs, boolean doETag, Long maxExpire) {
this(fs, doETag, maxExpire, NullTemplateHelper.INSTANCE, defMT);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param doETag If true, create an ETag value and send an ETag header with the resource.
@param defMime If the file system does not provide a mime-type attribute for the file, use this to set the
content-type header.
*/
public TemplateResources(FileSystem<? extends File> fs, boolean doETag, String defMime) {
this(fs, doETag, null, NullTemplateHelper.INSTANCE, defMime);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param maxExpire If not-null set the max expiration date header to this value.
@param parent When a resource cannot be loaded from the file system, delegate interpretation to this resource
factory.
*/
public TemplateResources(FileSystem<? extends File> fs, Long maxExpire, ResourceFactory parent) {
this(fs, false, maxExpire, parent, defMT);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param parent When a resource cannot be loaded from the file system, delegate interpretation to this resource
factory.
@param defMime If the file system does not provide a mime-type attribute for the file, use this to set the
content-type header.
*/
public TemplateResources(FileSystem<? extends File> fs, ResourceFactory parent, String defMime) {
this(fs, false, null, parent, defMime);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param maxExpire If not-null set the max expiration date header to this value.
@param defMime If the file system does not provide a mime-type attribute for the file, use this to set the
content-type header.
*/
public TemplateResources(FileSystem<? extends File> fs, Long maxExpire, String defMime) {
this(fs, false, maxExpire, NullTemplateHelper.INSTANCE, defMime);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param doETag If true, create an ETag value and send an ETag header with the resource.
@param parent When a resource cannot be loaded from the file system, delegate interpretation to this resource
factory.
@param defMime If the file system does not provide a mime-type attribute for the file, use this to set the
content-type header.
*/
public TemplateResources(FileSystem<? extends File> fs, boolean doETag, ResourceFactory parent, String defMime) {
this(fs, doETag, null, parent, defMime);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param doETag If true, create an ETag value and send an ETag header with the resource.
@param maxExpire If not-null set the max expiration date header to this value.
@param defMime If the file system does not provide a mime-type attribute for the file, use this to set the
content-type header.
*/
public TemplateResources(final FileSystem<? extends File> fs,
final boolean doETag,
final Long maxExpire,
final String defMime) {
this(fs, doETag, maxExpire, NullTemplateHelper.INSTANCE, defMime);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param maxExpire If not-null set the max expiration date header to this value.
@param parent When a resource cannot be loaded from the file system, delegate interpretation to this resource
factory.
@param defMime If the file system does not provide a mime-type attribute for the file, use this to set the
content-type header.
*/
public TemplateResources(final FileSystem<? extends File> fs,
final Long maxExpire,
final ResourceFactory parent,
final String defMime) {
this(fs, false, maxExpire, parent, defMime);
}
/** Create an instance.
@param fs The file system where scripts will be loaded from to be interpreted.
@param doETag If true, create an ETag value and send an ETag header with the resource.
@param maxExpire If not-null set the max expiration date header to this value.
@param parent When a resource cannot be loaded from the file system, delegate interpretation to this resource
factory.
@param defaultMime If the file system does not provide a mime-type attribute for the file, use this to set the
content-type header.
*/
public TemplateResources(final FileSystem<? extends File> fs,
final boolean doETag,
final Long maxExpire,
final ResourceFactory parent,
final String defaultMime) {
this.fs = fs;
this.doETag = doETag;
this.maxExpire = maxExpire;
this.parent = parent;
this.defaultMime = defaultMime;
this.loader = new Load(this);
}
/** Parse a string as a template resource, include syntax is NOT permitted in these templates.
@param template The string containing the template to parse.
@param mimeType The mime type of this template to return in the HTTP response evaluation produces.
@return a stand alone resource that will evaluate the template.
*/
public static Resource getStringAsResource(final String template, final String mimeType) {
final ArrayList<String> incPath = new ArrayList<>();
final Load loader = new Load(NullTemplateHelper.INSTANCE);
try {
final ByteArrayInputStream in = new ByteArrayInputStream(template.getBytes("UTF-8"));
return loader.construct(in, incPath, false, null, mimeType);
} catch (java.io.UnsupportedEncodingException uee) {
throw new AssertionError("UTF-8 should always be supported");
}
}
@Override public Resource get(final String urn) {
try {
final File<File> f = this.fs.get(urn);
try (final InputStream in = f.openInput()) {
if (in==null) { return parent.get(urn); }
final Object mt = f.getAttribute("MIMEType");
final String defaultMIMEType =
(mt instanceof String) ? (String) mt : ((mt == null) ? defaultMime : mt.toString());
final ArrayList<String> incPath = new ArrayList<String>();
incPath.add(urn);
return loader.construct(in, incPath, doETag, maxExpire, defaultMIMEType);
}
} catch (final RuntimeException | IOException ex) {
return parent.get(urn);
}
}
}