/**
* Copyright (c) 2012-2015 Edgar Espina
*
* This file is part of Handlebars.java.
*
* 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.github.jknack.handlebars.io;
import static org.apache.commons.lang3.Validate.notEmpty;
import static org.apache.commons.lang3.Validate.notNull;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import com.github.jknack.handlebars.Handlebars;
/**
* An {@link URL} {@link TemplateSource}.
*
* @author edgar.espina
* @since 0.11.0
*/
public class URLTemplateSource extends AbstractTemplateSource {
/**
* The resource. Required.
*/
private URL resource;
/**
* The last modified date.
*/
private Long lastModified;
/**
* The file's name.
*/
private String filename;
/**
* Creates a new {@link URLTemplateSource}.
*
* @param filename The file's name.
* @param resource The resource. Required.
*/
public URLTemplateSource(final String filename, final URL resource) {
this.filename = notEmpty(filename, "The filename is required.");
this.resource = notNull(resource, "A resource is required.");
}
@Override
public String content() throws IOException {
Reader reader = null;
final int bufferSize = 1024;
try {
reader = reader();
char[] cbuf = new char[bufferSize];
StringBuilder sb = new StringBuilder(bufferSize);
int len;
while ((len = reader.read(cbuf, 0, bufferSize)) != -1) {
sb.append(cbuf, 0, len);
}
return sb.toString();
} finally {
if (reader != null) {
reader.close();
}
}
}
@Override
public String filename() {
return filename;
}
@Override
public long lastModified() {
synchronized (this) {
if (lastModified == null) {
lastModified = lastModified(resource);
}
return lastModified;
}
}
/**
* Open the stream under the URL.
*
* @return A reader.
* @throws IOException If the stream can't be opened.
*/
protected Reader reader() throws IOException {
InputStream in = resource.openStream();
return new InputStreamReader(in, "UTF-8");
}
/**
* Read the last modified date from a resource.
*
* @param resource The resource.
* @return The last modified date from a resource.
* @throws IOException
*/
private long lastModified(final URL resource) {
URLConnection uc = null;
try {
uc = resource.openConnection();
if (uc instanceof JarURLConnection) {
URL jarURL = ((JarURLConnection) uc).getJarFileURL();
if (jarURL.getProtocol().equals("file")) {
uc = null;
String file = jarURL.getFile();
return new File(file).lastModified();
}
}
return uc.getLastModified();
} catch (IOException ex) {
Handlebars.warn("Can't get last modified date of: %s", resource);
return -1;
} finally {
try {
if (uc != null) {
// http://stackoverflow.com/questions/2057351/how-do-i-get-the-last-modification-time-of
// -a-java-resource
InputStream is = uc.getInputStream();
if (is != null) {
is.close();
}
}
} catch (IOException e) {
Handlebars.warn("Can't close: %s", resource);
}
}
}
}