ratpack.file.internal.FileSystemChecksumServices Maven / Gradle / Ivy
/*
* Copyright 2014 the original author or authors.
*
* 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 ratpack.file.internal;
import ratpack.file.FileSystemBinding;
import ratpack.file.checksummer.internal.Adler32Checksummer;
import ratpack.file.checksummer.internal.MD5Checksummer;
import ratpack.func.Function;
import ratpack.server.ServerConfig;
import java.io.InputStream;
import java.util.List;
import java.util.Arrays;
import java.util.concurrent.Executors;
import java.nio.file.Files;
/**
* Factory methods for creating {@link FileSystemChecksumService}.
*
* Checksum service is used for calculation of file system checksums - assets or any kind of files.
* Checksum service is backed by either predefined checksum calculation function (Noop. Adler32, MD5), or custom function.
* Custom function has to be provided in the form of {@code Function} (class implementing this interface or lambda expression).
* If checksummer function is not provided then Noop (no operation) calculation method is used. It does nothing, returns empty string as checksum.
*
*
* {@code
* import ratpack.file.internal.FileSystemChecksumService;
* import ratpack.file.internal.FileSystemChecksumServices;
* import ratpack.handling.Context;
* import ratpack.handling.Handler;
* import ratpack.test.handling.RequestFixture;
* import ratpack.test.handling.HandlingResult;
* import static org.junit.Assert.assertNotNull;
* import java.nio.file.Paths;
*
* public class Test {
* public static class MyHandler implements Handler {
* public void handle(Context ctx) throws Exception {
* FileSystemChecksumService service = FileSystemChecksumServices.adler32(ctx.getServerConfig(), "assets", "css", "js", "png", "svg");
* try {
* String chksum = service.checksum("styles/ratpack.css");
* ctx.render(chksum);
* }
* catch (Exception ex) {
* ctx.clientError(400);
* }
* }
* }
*
* public static void main(String... args) throws Exception {
* // Paths.get(".") -> indicates ratpack-manual home folder.
* HandlingResult result = RequestFixture.requestFixture()
* .serverConfig(Paths.get("../ratpack-site/src/ratpack"), b -> {
* })
* .handle(new MyHandler());
* assertNotNull(result.rendered(String.class));
* }
* }
* }
*/
public abstract class FileSystemChecksumServices {
private FileSystemChecksumServices() {
}
/**
* Get checksum service that is backward compatible - calculates file checksum with Adler32 method.
*
* @param serverConfig current server configuration. The most important parameter is baseDir. File path taken as parameter to checksummer is calculated relative to baseDir.
* @return file system checksummer service
*/
public static FileSystemChecksumService service(ServerConfig serverConfig) {
return service(serverConfig, new Adler32Checksummer());
}
/**
* Get checksum service with calculation method given as checksummer function.
* If checksummerFunc is not provided then noop method (no calculation) is used.
*
* @param serverConfig current server configuration. The most important parameter is baseDir. File path taken as parameter to checksummer is calculated relative to baseDir.
* @param checksummerFunc checksum calculation function that takes InputStream and return String with checksum value.
* @return file system checksummer service
*/
public static FileSystemChecksumService service(ServerConfig serverConfig, Function super InputStream, ? extends String> checksummerFunc) {
return service(serverConfig, checksummerFunc, null);
}
/**
* Get checksum service for additional path related to server's base dir and calculation method as checksummer function.
* Apply file filtering by extension: js, css, png filter files in target path.
* If checksummer function is not provided then noop method is used (no checksum calculation).
* If additional path is not given then server's base dir is used.
* If additional path is not correct path definition (contains illegal characters) or is not existing directory, IllegalArgumentException is thrown.
* If fileEndsWith variable length argument is not given then checksum may be calculated for file with any extension.
* If fileEndsWith is given and file's extension no match NoSuchFileException is thrown.
*
* @param serverConfig server configuration. The most important parameter is baseDir. File path taken as parameter to checksummer is calculated relative to baseDir and additional path.
* @param checksummerFunc checksum calculation function
* @param path additional path calculated relative to server's base dir. Becomes root for checksummer function.
* @param fileEndsWith variable length array of extenstions filtering files in target path
* @return file system checksummer service
*/
public static FileSystemChecksumService service(ServerConfig serverConfig, Function super InputStream, ? extends String> checksummerFunc, String path, String... fileEndsWith) {
Function super InputStream, ? extends String> checksummer = checksummerFunc != null ? checksummerFunc : noopChecksummer();
FileSystemBinding fsb = path != null ? serverConfig.getBaseDir().binding(path) : serverConfig.getBaseDir();
List exts = Arrays.asList(fileEndsWith);
if (fsb == null || !Files.isDirectory(fsb.getFile())) {
throw new IllegalArgumentException("Non existing path related to server's base dir.");
}
DefaultFileSystemChecksumService service = new DefaultFileSystemChecksumService(fsb, checksummer, exts);
if (serverConfig.isDevelopment()) {
return service;
} else {
CachingFileSystemChecksumService cachingService = new CachingFileSystemChecksumService(service);
new FileSystemChecksumServicePopulater(fsb.getFile(), exts, cachingService, Executors.newFixedThreadPool(5), 4).start();
return cachingService;
}
}
/**
* Get checksum service with Adler32 calculation method.
*
* @param serverConfig current server configuration. The most important parameter is baseDir. File path taken as parameter to checksummer is calculated relative to baseDir.
* @param path additional path related to server's base dir. Becomes root for checksummer function. Optional argument.
* @param fileEndsWith variable length array of extenstions filtering files in target path
* @return file system checksummer service
*/
public static FileSystemChecksumService adler32(ServerConfig serverConfig, String path, String... fileEndsWith) {
return service(serverConfig, new Adler32Checksummer(), path, fileEndsWith);
}
/**
* Get checksum service with MD5 calculation method.
*
* @param serverConfig current server configuration. The most important parameter is baseDir. File path taken as parameter to checksummer is calculated relative to baseDir.
* @param path additional path related to server's base dir. Becomes root for checksummer function. Optional argument.
* @param fileEndsWith variable length array of extenstions filtering files in target path
* @return file system checksummer service
*/
public static FileSystemChecksumService md5(ServerConfig serverConfig, String path, String... fileEndsWith) {
return service(serverConfig, new MD5Checksummer(), path, fileEndsWith);
}
/**
* Return checksummer that does nothing. Does not calculate checksum and instead returns empty string.
* @return checksummer function that returns empty checksum.
*/
private static Function noopChecksummer() {
return (InputStream is) -> {
return "";
};
}
}