![JAR search and dependency download from the Maven repository](/logo.png)
de.agilecoders.wicket.webjars.collectors.AssetsMap Maven / Gradle / Ivy
The newest version!
package de.agilecoders.wicket.webjars.collectors;
import de.agilecoders.wicket.webjars.WicketWebjars;
import de.agilecoders.wicket.webjars.settings.IWebjarsSettings;
import de.agilecoders.wicket.webjars.util.Helper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static de.agilecoders.wicket.webjars.util.Helper.reversePath;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* asset holder map.
*
* @author miha
*/
public class AssetsMap implements IAssetProvider, IRecentVersionProvider {
private static final Logger LOG = LoggerFactory.getLogger(WicketWebjars.class);
private final IWebjarsSettings settings;
private final SortedMap fullPathIndex;
private final AssetPathCollector[] collectors;
private final String recentVersionPlaceHolder;
/**
* Construct.
*
* @param settings the settings to use.
*/
public AssetsMap(IWebjarsSettings settings) {
this.settings = settings;
this.collectors = settings.assetPathCollectors();
this.recentVersionPlaceHolder = settings.recentVersionPlaceHolder();
this.fullPathIndex = new TreeMap<>();
reindex();
}
public AssetsMap reindex() {
final Pattern resourcePattern = settings.resourcePattern();
final ClassLoader[] classLoaders = settings.classLoaders();
final SortedMap _fullPathIndex = createFullPathIndex(resourcePattern, classLoaders);
fullPathIndex.clear();
fullPathIndex.putAll(_fullPathIndex);
return this;
}
@Override
public String findRecentVersionFor(String path) {
final String partialPath = Helper.prependWebjarsPathIfMissing(path);
final Matcher partialPathMatcher = settings.webjarsPathPattern().matcher(partialPath);
if (partialPathMatcher.find() && recentVersionPlaceHolder.equalsIgnoreCase(partialPathMatcher.group(2))) {
final Set assets = listAssets(partialPathMatcher.group(1));
final String fileName = "/" + partialPathMatcher.group(3);
final Set versions = new HashSet<>();
for (String asset : assets) {
if (asset.endsWith(fileName)) {
final Matcher matcher = settings.webjarsPathPattern().matcher(asset);
if (matcher.find()) {
versions.add(matcher.group(2));
}
}
}
if (versions.size() == 1) {
return versions.iterator().next();
} else if (versions.size() > 1) {
final String first = versions.iterator().next();
LOG.warn("More than one version of a webjars resource has been found in the classpath. " +
"This is not supported! Webjars resource: {}; available versions: {}; going to use: {}",
fileName, versions, first);
return first;
} else {
LOG.debug("No version found for webjars resource: {}", partialPath);
}
} else {
LOG.trace("given webjars resource isn't a dynamic versioned one: {}", partialPath);
}
return null;
}
@Override
public SortedMap getFullPathIndex() {
return fullPathIndex;
}
@Override
public Set listAssets(final String folderPath) {
final Collection allAssets = getFullPathIndex().values();
final Set assets = new HashSet<>();
final String prefix;
final String webjarsPath = settings.webjarsPath();
if (webjarsPath.endsWith("/")) {
prefix = webjarsPath + Helper.removeLeadingSlash(folderPath);
} else {
prefix = webjarsPath + Helper.prependLeadingSlash(folderPath);
}
for (final String asset : allAssets) {
if (asset.startsWith(prefix)) {
assets.add(asset);
}
}
return assets;
}
/**
* Return all {@link URL}s found in webjars directory,
* either identifying JAR files or plain directories.
*/
private Set listWebjarsParentURLs(final ClassLoader[] classLoaders) {
final Set urls = new HashSet<>();
final String webjarsPath = settings.webjarsPath();
for (final ClassLoader classLoader : classLoaders) {
try {
final Enumeration enumeration = classLoader.getResources(webjarsPath);
while (enumeration.hasMoreElements()) {
urls.add(enumeration.nextElement());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return urls;
}
/**
* Return all of the resource paths filtered given an expression and a list of class loaders.
*/
private Set getAssetPaths(final Pattern filterExpr, final ClassLoader... classLoaders) {
final Set assetPaths = new HashSet<>();
final Set urls = listWebjarsParentURLs(classLoaders);
for (final URL url : urls) {
for (AssetPathCollector collector : collectors) {
if (collector.accept(url)) {
Collection collection = collector.collect(url, filterExpr);
assetPaths.addAll(collection);
}
}
}
return assetPaths;
}
/**
* Return a map that can be used to perform index lookups of partial file paths. This index constitutes a key that is the reverse form of the path
* it relates to. Thus if a partial lookup needs to be performed from the rightmost path components then the key to access can be expressed easily
* e.g. the path "a/b" would be the map tuple "b/a" -> "a/b". If we need to look for an asset named "a" without knowing the full path then we can
* perform a partial lookup on the sorted map.
*
* @param filterExpr the regular expression to be used to filter resources that will be included in the index.
* @param classLoaders the class loaders to be considered for loading the resources from.
* @return the index.
*/
private SortedMap createFullPathIndex(final Pattern filterExpr, final ClassLoader... classLoaders) {
final Set assetPaths = getAssetPaths(filterExpr, classLoaders);
final SortedMap assetPathIndex = new TreeMap<>();
for (final String assetPath : assetPaths) {
assetPathIndex.put(reversePath(assetPath), assetPath);
}
return assetPathIndex;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy