blob: 8fcf2112e84042b1d1d663cf68733a2a514d43bd [file] [log] [blame]
/*
* Copyright (C) 2010 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.clearsilver.jsilver.adaptor;
import com.google.clearsilver.jsilver.exceptions.JSilverTemplateNotFoundException;
import com.google.clearsilver.jsilver.resourceloader.ResourceLoader;
import org.clearsilver.CSFileLoader;
import org.clearsilver.CSUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.util.List;
/**
* Wrap a CSFileLoader with a ResourceLoader
*/
public class ResourceLoaderAdaptor implements ResourceLoader {
private final JHdf hdf;
private final LoadPathToFileCache loadPathCache;
private final CSFileLoader csFileLoader;
private List<String> loadPaths;
ResourceLoaderAdaptor(JHdf hdf, LoadPathToFileCache loadPathCache, CSFileLoader csFileLoader) {
this.hdf = hdf;
this.loadPathCache = loadPathCache;
this.csFileLoader = csFileLoader;
}
@Override
public Reader open(String name) throws IOException {
if (csFileLoader != null) {
if (hdf.getData() == null) {
throw new IllegalStateException("HDF is already closed");
}
return new StringReader(csFileLoader.load(hdf, name));
} else {
File file = locateFile(name);
if (file == null) {
throw new FileNotFoundException("Could not locate file " + name);
}
return new InputStreamReader(new FileInputStream(file), "UTF-8");
}
}
@Override
public Reader openOrFail(String name) throws JSilverTemplateNotFoundException, IOException {
Reader reader = open(name);
if (reader == null) {
final StringBuffer text = new StringBuffer();
text.append("No file '");
text.append(name);
text.append("' ");
if (loadPaths == null || loadPaths.isEmpty()) {
text.append("with no load paths");
} else if (loadPaths.size() == 1) {
text.append("inside directory '");
text.append(loadPaths.get(0));
text.append("'");
} else {
text.append("inside directories ( ");
for (String path : getLoadPaths()) {
text.append("'");
text.append(path);
text.append("' ");
}
text.append(")");
}
throw new JSilverTemplateNotFoundException(text.toString());
} else {
return reader;
}
}
/**
*
* @param name name of the file to locate.
* @return a File object corresponding to the existing file or {@code null} if it does not exist.
*/
File locateFile(String name) {
if (name.startsWith(File.separator)) {
// Full path to file was given.
File file = newFile(name);
return file.exists() ? file : null;
}
File file = null;
// loadPathCache is null when load path caching is disabled at the
// JSilverFactory level. This is implied by setting cache size
// to 0 using JSilverOptions.setLoadPathCacheSize(0).
if (loadPathCache != null) {
String filePath = loadPathCache.lookup(getLoadPaths(), name);
if (filePath != null) {
file = newFile(filePath);
return file.exists() ? file : null;
}
}
file = locateFile(getLoadPaths(), name);
if (file != null && loadPathCache != null) {
loadPathCache.add(getLoadPaths(), name, file.getAbsolutePath());
}
return file;
}
/**
* Given an ordered list of directories to look in, locate the specified file. Returns
* <code>null</code> if file not found.
* <p>
* This is copied from {@link org.clearsilver.CSUtil#locateFile(java.util.List, String)} but has
* one important difference. It calls our subclassable newFile method.
*
* @param loadPaths the ordered list of paths to search.
* @param filename the name of the file.
* @return a File object corresponding to the file. <code>null</code> if file not found.
*/
File locateFile(List<String> loadPaths, String filename) {
if (filename == null) {
throw new NullPointerException("No filename provided");
}
if (loadPaths == null) {
throw new NullPointerException("No loadpaths provided.");
}
for (String path : loadPaths) {
File file = newFile(path, filename);
if (file.exists()) {
return file;
}
}
return null;
}
/**
* Separate methods to allow tests to subclass and override File creation and return mocks or
* fakes.
*/
File newFile(String filename) {
return new File(filename);
}
File newFile(String path, String filename) {
return new File(path, filename);
}
@Override
public void close(Reader reader) throws IOException {
reader.close();
}
@Override
public Object getKey(String filename) {
if (filename.startsWith(File.separator)) {
return filename;
} else {
File file = locateFile(filename);
if (file == null) {
// The file does not exist, use the full loadpath and file name as the
// key.
return LoadPathToFileCache.makeCacheKey(getLoadPaths(), filename);
} else {
return file.getAbsolutePath();
}
}
}
/**
* Some applications, e.g. online help, need to know when a file has changed due to a symlink
* modification hence the use of {@link File#getCanonicalFile()}, if possible.
*/
@Override
public Object getResourceVersionId(String filename) {
File file = locateFile(filename);
if (file == null) {
return null;
}
String fullPath;
try {
fullPath = file.getCanonicalPath();
} catch (IOException e) {
fullPath = file.getAbsolutePath();
}
return String.format("%s@%s", fullPath, file.lastModified());
}
final CSFileLoader getCSFileLoader() {
return csFileLoader;
}
private synchronized List<String> getLoadPaths() {
if (loadPaths == null) {
if (hdf.getData() == null) {
throw new IllegalStateException("HDF is already closed");
}
loadPaths = CSUtil.getLoadPaths(hdf, true);
}
return loadPaths;
}
}