Skip to content

Commit e2ff638

Browse files
authored
Merge pull request #19 from dodgex/18-inconsitent-path-behaviour
Ensure consistent behaviour for path and fullPath
2 parents 44af289 + f6bf824 commit e2ff638

File tree

2 files changed

+87
-25
lines changed

2 files changed

+87
-25
lines changed

src/main/java/org/webjars/WebJarVersionLocator.java

+81-24
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,28 @@
1414

1515

1616
/**
17-
* Locate WebJar version. The class is thread safe.
17+
* Helper Class to locate WebJar versions.
18+
*
19+
* <p>By default, this class only supports looking up official WebJars with the Maven group IDs of {@code org.webjars.npm} and {@code org.webjars}.
20+
*
21+
* <p>Custom WenJars can be registered by providing a {@code META-INF/resources/webjars-locator.properties} file.
22+
*
23+
* <p><b>Note:</b> It is recommended, to add this file directly to the custom WebJar to ease the usage.
24+
* But for WebJars not providing the file, you can add a {@code webjars-locator.properties} to your project.
25+
*
26+
* <p>Example file (multiple WebJars can be provided, one per line):
27+
* <pre>{@code
28+
* mywebjar.version=3.2.1
29+
* anotherwebjar.version=1.4.3
30+
* }</pre>
31+
*
32+
* <p>As the lookup of all {@code webjars-locator.properties} files happens during the construction of the class
33+
* and the found versions are directly added to the cache, these property files can and will override versions
34+
* that otherwise would be looked up by {@link WebJarVersionLocator#version(String)}.
35+
*
36+
* <p>When multiple {@code webjars-locator.properties} files contain a version for the same WebJar, the one that has been found first wins.
37+
*
38+
* <p>The class is thread safe.
1839
*/
1940
@NullMarked
2041
public class WebJarVersionLocator {
@@ -47,47 +68,83 @@ public WebJarVersionLocator() {
4768
}
4869

4970
/**
50-
* @param webJarName The name of the WebJar, i.e. bootstrap
51-
* @param exactPath The path to the file within the WebJar, i.e. js/bootstrap.js
52-
* @return The full path to the file in the classpath including the version, i.e. META-INF/resources/webjars/bootstrap/3.1.1/js/bootstrap.js
71+
* Builds the versioned path for a file of a WebJar within the standard WebJar classpath location (see {@link WebJarVersionLocator#WEBJARS_PATH_PREFIX}).
72+
*
73+
* <p>The path is built by prefixing the versioned path built by {@link WebJarVersionLocator#path(String, String)} with the standard WebJars location classpath.
74+
*
75+
* <p>See {@link WebJarVersionLocator#path(String, String)} for a detailed explanation of how the versioned file path is built.
76+
*
77+
* <p><b>Note:</b> This method does not perform any checks if the resulting path references an existing file.
78+
*
79+
* @param webJarName The name of the WebJar, this is the directory in the standard WebJar classpath location, usually the same as the Maven artifact ID
80+
* @param filePath The path to the file within the WebJar
81+
* @return The versioned path to the file in the classpath, if a version has been found, otherwise {@code null}
82+
* @see WebJarVersionLocator#path(String, String)
83+
* @see WebJarVersionLocator#WEBJARS_PATH_PREFIX
5384
*/
5485
@Nullable
55-
public String fullPath(final String webJarName, final String exactPath) {
56-
final String version = version(webJarName);
86+
public String fullPath(final String webJarName, final String filePath) {
87+
final String path = path(webJarName, filePath);
5788

58-
if (!isEmpty(version)) {
59-
// todo: not sure why we check this
60-
if (!exactPath.startsWith(version)) {
61-
return String.format("%s/%s/%s/%s", WEBJARS_PATH_PREFIX, webJarName, version, exactPath);
62-
}
63-
else {
64-
return String.format("%s/%s/%s", WEBJARS_PATH_PREFIX, webJarName, exactPath);
65-
}
89+
if (notEmpty(path)) {
90+
return String.format("%s/%s", WEBJARS_PATH_PREFIX, path);
6691
}
6792

6893
return null;
6994
}
7095

7196
/**
97+
* Builds the versioned path for a file of a WebJar relative to the standard WebJar classpath location (see {@link WebJarVersionLocator#WEBJARS_PATH_PREFIX}).
98+
*
99+
* <p>The path is built by joining the {@code webJarName}, the known version and the {@code filePath}, if no version (from classpath checking) is known for the WebJar this method returns {@code null}.
100+
*
101+
* <p><b>Note:</b> In cases where the {@code filePath} parameter already starts with the known version of the WebJar, the version will not be added again. But it is recommended that you do NOT include a hard-coded version when looking up WebJar file paths.
72102
*
73-
* @param webJarName The name of the WebJar, i.e. bootstrap
74-
* @param exactPath The path to the file within the WebJar, i.e. js/bootstrap.js
75-
* @return The path to the file in the standard WebJar classpath location, including the version, i.e. bootstrap/3.1.1/js/bootstrap.js
103+
* <pre>{@code
104+
* // returns "bootstrap/3.1.1/css/bootstrap.css"
105+
* locator.path("bootstrap", "css/bootstrap.css");
106+
*
107+
* // returns "bootstrap/3.1.1/css/bootstrap.css" as well
108+
* locator.path("bootstrap", "3.1.1/css/bootstrap.css");
109+
*
110+
* // returns null, assuming there is no "unknown" WebJar
111+
* locator.path("unknown", "some/file.css");
112+
* }</pre>
113+
*
114+
* <p><b>Note:</b> This method does not perform any checks if the resulting path references an existing file.
115+
*
116+
* @param webJarName The name of the WebJar, this is the directory in the standard WebJar classpath location, usually the same as the Maven artifact ID
117+
* @param filePath The path to the file within the WebJar
118+
* @return The versioned path relative to the standard WebJar classpath location, if a version has been found, otherwise {@code null}
119+
* @see WebJarVersionLocator#fullPath(String, String)
120+
* @see WebJarVersionLocator#WEBJARS_PATH_PREFIX
76121
*/
77122
@Nullable
78-
public String path(final String webJarName, final String exactPath) {
123+
public String path(final String webJarName, final String filePath) {
79124
final String version = version(webJarName);
80125

81-
if (!isEmpty(version)) {
82-
return String.format("%s/%s/%s", webJarName, version, exactPath);
126+
if (notEmpty(version)) {
127+
if (filePath.startsWith(version)) {
128+
return String.format("%s/%s", webJarName, filePath);
129+
} else {
130+
return String.format("%s/%s/%s", webJarName, version, filePath);
131+
}
83132
}
84133

85134
return null;
86135
}
87136

88137
/**
89-
* @param webJarName The name of the WebJar, i.e. bootstrap
90-
* @return The version of the WebJar, i.e 3.1.1
138+
* This method tries to determine the available version for a WebJar in the classpath.
139+
*
140+
* <p>For official WebJars, the version lookup is performed by checking for a {@code pom.properties} file for either {@link WebJarVersionLocator#NPM}
141+
* or {@link WebJarVersionLocator#PLAIN} WebJars within {@code META-INF/maven}. The lookup result is cached.
142+
*
143+
* <p>Custom WebJars can be registered by using a {@code webjars-locator.properties} file. See {@link WebJarVersionLocator} for details.
144+
*
145+
* @param webJarName The name of the WebJar, this is the directory in the standard WebJar classpath location, usually the same as the Maven artifact ID
146+
* @return The version of the WebJar, if found, otherwise {@code null}
147+
* @see WebJarVersionLocator
91148
*/
92149
@Nullable
93150
public String version(final String webJarName) {
@@ -168,8 +225,8 @@ private boolean hasResourcePath(final String webJarName, final String path) {
168225
return LOADER.getResource(WEBJARS_PATH_PREFIX + "/" + webJarName + "/" + path) != null;
169226
}
170227

171-
private boolean isEmpty(@Nullable final String str) {
172-
return str == null || str.trim().isEmpty();
228+
private boolean notEmpty(@Nullable final String str) {
229+
return str != null && !str.trim().isEmpty();
173230
}
174231

175232
}

src/test/java/org/webjars/WebJarVersionLocatorTest.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,15 @@ void path_exists_version_not_supplied() {
5555
}
5656

5757
@Test
58-
void full_path_exists_version_supplied() {
58+
void full_path_exists_with_version_supplied() {
5959
assertEquals(WebJarVersionLocator.WEBJARS_PATH_PREFIX + "/bootstrap/3.1.1/js/bootstrap.js", new WebJarVersionLocator().fullPath("bootstrap", "3.1.1/js/bootstrap.js"));
6060
}
6161

62+
@Test
63+
void path_exists_with_version_supplied() {
64+
assertEquals("bootstrap/3.1.1/js/bootstrap.js", new WebJarVersionLocator().path("bootstrap", "3.1.1/js/bootstrap.js"));
65+
}
66+
6267
@Test
6368
void cache_is_populated_on_lookup() {
6469
AtomicBoolean shouldInspect = new AtomicBoolean(false);

0 commit comments

Comments
 (0)