55
66import java .io .IOException ;
77import java .io .InputStream ;
8+ import java .net .URL ;
9+ import java .util .Enumeration ;
10+ import java .util .Map ;
811import java .util .Optional ;
912import java .util .Properties ;
1013import java .util .concurrent .ConcurrentHashMap ;
@@ -25,17 +28,22 @@ public class WebJarVersionLocator {
2528 private static final String NPM = "org.webjars.npm/" ;
2629 private static final String PLAIN = "org.webjars/" ;
2730 private static final String POM_PROPERTIES = "/pom.properties" ;
31+ private static final String LOCATOR_PROPERTIES = "META-INF/resources/webjars-locator.properties" ;
32+
33+ private static final String CACHE_KEY_PREFIX = "version-" ;
2834
2935 private static final ClassLoader LOADER = WebJarVersionLocator .class .getClassLoader ();
3036
3137 private final WebJarCache cache ;
3238
3339 public WebJarVersionLocator () {
3440 this .cache = new WebJarCacheDefault (new ConcurrentHashMap <>());
41+ readLocatorProperties ();
3542 }
3643
3744 WebJarVersionLocator (WebJarCache cache ) {
3845 this .cache = cache ;
46+ readLocatorProperties ();
3947 }
4048
4149 /**
@@ -83,7 +91,7 @@ public String path(final String webJarName, final String exactPath) {
8391 */
8492 @ Nullable
8593 public String version (final String webJarName ) {
86- final String cacheKey = "version-" + webJarName ;
94+ final String cacheKey = CACHE_KEY_PREFIX + webJarName ;
8795 final Optional <String > optionalVersion = cache .computeIfAbsent (cacheKey , (key ) -> {
8896 InputStream resource = LOADER .getResourceAsStream (PROPERTIES_ROOT + NPM + webJarName + POM_PROPERTIES );
8997 if (resource == null ) {
@@ -126,6 +134,36 @@ public String version(final String webJarName) {
126134 return optionalVersion .orElse (null );
127135 }
128136
137+ private void readLocatorProperties () {
138+ try {
139+ Enumeration <URL > resources = LOADER .getResources (LOCATOR_PROPERTIES );
140+ while (resources .hasMoreElements ()) {
141+ URL resourceUrl = resources .nextElement ();
142+ try (InputStream resource = resourceUrl .openStream ()) {
143+ Properties properties = new Properties ();
144+ properties .load (resource );
145+ for (Map .Entry <Object , Object > entry : properties .entrySet ()) {
146+ String webJarName = entry .getKey ().toString ();
147+ if (!webJarName .endsWith (".version" )) {
148+ // ".version" suffix is required
149+ continue ;
150+ }
151+
152+ webJarName = webJarName .substring (0 , webJarName .lastIndexOf (".version" ));
153+
154+ String version = entry .getValue ().toString ();
155+ if (hasResourcePath (webJarName , version )) {
156+ // Only add configured versions if their path exists
157+ cache .computeIfAbsent (CACHE_KEY_PREFIX + webJarName , x -> Optional .of (version ));
158+ }
159+ }
160+ }
161+ }
162+ } catch (IOException e ) {
163+ throw new RuntimeException ("unable to load locator properties" , e );
164+ }
165+ }
166+
129167 private boolean hasResourcePath (final String webJarName , final String path ) {
130168 return LOADER .getResource (WEBJARS_PATH_PREFIX + "/" + webJarName + "/" + path ) != null ;
131169 }
0 commit comments