asset.pipeline.fs.ClasspathAssetResolver.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of asset-pipeline-core Show documentation
Show all versions of asset-pipeline-core Show documentation
JVM Asset Pipeline library for serving static web assets, bundling, minifying, and extensibility for transpiling.
The newest version!
package asset.pipeline.fs
import asset.pipeline.AssetFile
import asset.pipeline.AssetHelper
import asset.pipeline.GenericAssetFile
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
/**
* Implementation of the {@link AssetResolver} interface for resolving files on the classpath.
* It is important to note that recursive scanning does not function unless an assets.list file is supplied
*
* @author David Estes
*/
@Slf4j
public class ClasspathAssetResolver extends AbstractAssetResolver {
static String NATIVE_FILE_SEPARATOR = File.separator
static String DIRECTIVE_FILE_SEPARATOR = '/'
ClassLoader classLoader
String prefixPath
String assetListPath
Collection assetList = []
ClasspathAssetResolver(String name, String basePath, String assetListPath=null, ClassLoader classLoader = Thread.currentThread().contextClassLoader) {
super(name)
this.classLoader = classLoader
this.prefixPath = basePath
this.assetListPath = assetListPath
loadAssetList()
}
private loadAssetList() {
if (!assetListPath) {
return
}
def resources = classLoader.getResources(assetListPath)
resources.each { URL res ->
assetList += res?.text?.tokenize("\n") ?: []
}
}
AssetFile getAsset(String relativePath, String contentType = null, String extension = null, AssetFile baseFile = null) {
if (!relativePath) {
return null
}
def normalizedPath = AssetHelper.normalizePath(relativePath.replace(NATIVE_FILE_SEPARATOR, DIRECTIVE_FILE_SEPARATOR))
if(!normalizedPath) {
return null
}
def specs
if (contentType) {
specs = AssetHelper.getPossibleFileSpecs(contentType)
} else {
if (!extension) {
extension = AssetHelper.extensionFromURI(relativePath)
}
specs = AssetHelper.assetFileClasses().findAll { it.extensions.contains(extension) }
}
AssetFile assetFile = resolveAsset(specs, prefixPath, normalizedPath, baseFile, extension)
return assetFile
}
protected Closure createInputStreamClosure(URL file) {
if (file) {
return { -> new BufferedInputStream(file.openStream(), 512) }
}
return null
}
String relativePathToResolver(URL file, String scanDirectoryPath) {
if (!file) {
return null
}
def filePath = file.path
if (filePath.contains(scanDirectoryPath)) {
def i = filePath.indexOf(scanDirectoryPath)
return filePath.substring(i + scanDirectoryPath.size() + 1)
} else {
throw new RuntimeException("File was not sourced from the same ScanDirectory ${filePath}")
}
}
@CompileStatic
URL getRelativeFile(String relativePath, String name) {
if (name.startsWith('/')) {
name = name.substring(1)
}
URL file = classLoader.getResource("$relativePath/$name")
if (file?.getProtocol()?.equals("file")) {
if(new File(file.getPath()).isDirectory()) {
return null
}
} else if(file?.getPath()?.endsWith("/")) {
return null
}
return file
}
@Override
@CompileStatic
protected String getFileName(URL url) {
String path = url.path
String name = path
if (path.lastIndexOf('/'))
name = path.substring(path.lastIndexOf('/'))
return name
}
@CompileStatic
List getAssets(String basePath, String contentType = null, String extension = null, Boolean recursive = true, AssetFile relativeFile = null, AssetFile baseFile = null) {
def specs
if (contentType) {
specs = AssetHelper.getPossibleFileSpecs(contentType)
}
if (!assetList) {
return []
}
def extensions = []
if (extension) {
extensions << extension
} else if (specs) {
for (spec in specs) {
if(spec.extensions) {
extensions.addAll(spec.extensions)
}
}
}
String translatedBasePath = basePath
if (!basePath.startsWith('/') && relativeFile != null) {
List pathArgs = relativeFile.parentPath ? relativeFile.parentPath.split(DIRECTIVE_FILE_SEPARATOR).toList() : new ArrayList()
//(path should be relative not canonical)
String[] basePathArgs = basePath.split(DIRECTIVE_FILE_SEPARATOR)
List parentPathArgs = pathArgs ? pathArgs[0..(pathArgs.size() - 1)] as List : [] as List
parentPathArgs.addAll(basePathArgs.toList() as List)
translatedBasePath = (parentPathArgs).join(DIRECTIVE_FILE_SEPARATOR)
translatedBasePath = AssetHelper.normalizePath(translatedBasePath)
translatedBasePath = translatedBasePath ? (translatedBasePath + "/") : null
}
List tree = []
for (String filePath in assetList) {
if (!translatedBasePath || filePath.startsWith(translatedBasePath)) {
String[] mimeType = AssetHelper.assetMimeTypeForURI(filePath).toArray(new String[0])
def url = classLoader.getResource("$prefixPath/$filePath")
if (url && mimeType && contentType in mimeType) {
tree << assetForFile(url, contentType, baseFile, prefixPath)
}
}
}
return tree
}
/**
* Uses file globbing to scan for files that need precompiled
*/
public Collection scanForFiles(List excludePatterns, List includePatterns) {
def fileList = []
List excludedPatternList = excludePatterns ? excludePatterns : new ArrayList()
List includedPatternList = includePatterns ? includePatterns : new ArrayList()
for (String relativePath in assetList) {
def entry = classLoader.getResource("$prefixPath/$relativePath")
if (entry && !isFileMatchingPatterns(relativePath, excludedPatternList) || isFileMatchingPatterns(relativePath, includedPatternList)) {
def assetFileClass = AssetHelper.assetForFileName(relativePath)
if (assetFileClass) {
fileList << assetFileClass.newInstance(inputStreamSource: createInputStreamClosure(entry), path: relativePath, sourceResolver: this)
} else {
fileList << new GenericAssetFile(inputStreamSource: createInputStreamClosure(entry), path: relativePath)
}
}
}
return fileList.unique { AssetFile a, AssetFile b -> a.path <=> b.path }
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy