Skip to content

Commit 3903b22

Browse files
committed
Add ToC and JarUtils info; add JarUtils attributions
1 parent f6fd179 commit 3903b22

File tree

2 files changed

+61
-7
lines changed

2 files changed

+61
-7
lines changed

README.md

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,34 @@
44

55
**Nordstrom Java Utils** is a small collection of general-purpose utility classes with wide applicability.
66

7+
## What You'll Find Here
8+
9+
* [UncheckedThrow](#uncheckedthrow) provides a method that uses type erasure to enable you to throw checked exception as unchecked.
10+
* [DatabaseUtils](#databaseutils) provides facilities that enable you to define collections of database queries and stored procedures in an easy-to-execute format.
11+
* [Query Collections](#query-collections) are defined as Java enumerations that implement the `QueryAPI` interface
12+
* [Stored Procedure Collections](#stored-procedure-collections) are defined as Java enumerations that implement the `SProcAPI` interface
13+
* [Recommended Implementation Strategies](#recommended-implementation-strategies) to maximize usability and configurability
14+
* [Query Collection Example](#query-collection-example)
15+
* [Registering JDBC Providers](#registering-jdbc-providers) with the **ServiceLoader** facility of **DatabaseUtils**
16+
* [PathUtils](#pathutils) provides a method to acquire the next file path in sequence for the specified base name and extension in the indicated target folder.
17+
* [Params Interface](#params-interface) defines concise methods for the creation of named parameters and parameter maps.
18+
* [JarUtils](#jarutils) provides methods related to Java JAR files:
19+
* [Assembling a Classpath String](#assembling-a-classpath-string)
20+
* [Finding a JAR File Path](#finding-a-jar-file-path)
21+
* [Extracting the `Premain-Class` Attribute](#extracting-the-premain-class-attribute)
22+
723
## UncheckedThrow
824

925
The **UncheckedThrow** class uses type erasure to enable client code to throw checked exceptions as unchecked. This allows methods to throw checked exceptions without requiring clients to handle or declare them. It should be used judiciously, as this exempts client code from handling or declaring exceptions created by their own actions. The target use case for this facility is to throw exceptions that were serialized in responses from a remote system. Although the compiler won't require clients of methods using this technique to handle or declare the suppressed exception, the JavaDoc for such methods should include a `@throws` declaration for implementers who might want to handle or declare it voluntarily.
1026

11-
1227
```java
1328
...
1429

1530
String value;
1631
try {
1732
value = URLDecoder.decode(keyVal[1], "UTF-8");
1833
} catch (UnsupportedEncodingException e) {
19-
       throw UncheckedThrow.throwUnchecked(e);
34+
throw UncheckedThrow.throwUnchecked(e);
2035
}
2136

2237
...
@@ -255,7 +270,7 @@ This sample provider configuration file will cause **DatabaseUtils** to load the
255270

256271
## PathUtils
257272

258-
The **PathUtils** `getNextPath` method provides a method to acquire the next file path in sequence for the specified base name and extension in the indicated target folder. If the target folder already contains at least one file that matches the specified base name and extension, the algorithm used to select the next path will always return a path whose index is one more than the highest index that currently exists. (If a single file with no index is found, its implied index is 0.)
273+
The **PathUtils** class provides a method to acquire the next file path in sequence for the specified base name and extension in the indicated target folder. If the target folder already contains at least one file that matches the specified base name and extension, the algorithm used to select the next path will always return a path whose index is one more than the highest index that currently exists. (If a single file with no index is found, its implied index is 0.)
259274

260275
##### Example usage of `getNextPath`
261276

@@ -342,3 +357,30 @@ public class ParamTest implements Params {
342357
```
343358

344359
This code uses a static import to eliminate redundant references to the **Params** interface. It also shows the unrestricted data types of parameter values. The use of **Optional** objects enables you to provide an indication that no value was returned without the risks associated with `null`.
360+
361+
## JarUtils
362+
363+
The **JarUtils** class provides methods related to Java JAR files.
364+
365+
* `getClasspath` assemble a classpath string from the specified array of dependencies.
366+
* `findJarPathFor` find the path to the JAR file from which the named class was loaded.
367+
* `getJarPremainClass` gets the 'Premain-Class' attribute from the indicated JAR file.
368+
369+
The methods of this class provide critical services for the `Local Grid` feature of [**Selenium Foundation**](https://github.com/sbabcoc/Selenium-Foundation), handling the task of locating the JAR files that declare the classes required by the Java-based servers it launches.
370+
371+
### Assembling a Classpath String
372+
373+
The **`getClasspath`** method assembles a classpath string from the specified array of dependency contexts. This is useful for launching a Java sub-process, as it greatly simplifies the task of collecting the paths of JAR files that declare the classes required by your process. If any of the specified dependency contexts names the `premain` class of a Java agent, the string returned by this method will contain two records delimited by a `newline` character:
374+
375+
* `0` - assembled classpath string
376+
* `1` - tab-delimited list of Java agent paths
377+
378+
### Finding a JAR File Path
379+
380+
The **`findJarPathFor`** method will find the absolute path to the JAR file from which the named class was loaded, provided the class has been loaded from a JAR file on the local file system.
381+
382+
### Extracting the `Premain-Class` Attribute
383+
384+
The **`getJarPremainClass`** method will extract the `Premain-Class` attribute from the manifest of the indicated JAR file. The value of this attribute specifies the name of a `Java agent` class declared by the JAR.
385+
386+
> Written with [StackEdit](https://stackedit.io/).

src/main/java/com/nordstrom/common/jar/JarUtils.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@
2323
* <li>{@link #findJarPathFor} find the path to the JAR file from which the named class was loaded.</li>
2424
* <li>{@link #getJarPremainClass} gets the 'Premain-Class' attribute from the indicated JAR file.</li>
2525
* </ul>
26+
*
27+
* <b>NOTE</b>: The core implementation for the {@link #findJarPathFor(String)} method was shared on
28+
* <a href="https://stackoverflow.com">Stack Overflow</a> by <a href="https://stackoverflow.com/users/125844/notnoop">
29+
* notnoop</a> in their <a href="https://stackoverflow.com/a/1983875">answer</a> to a question regarding
30+
* how to locate the JAR file from which a specified class was loaded. This code was attributed to the
31+
* <a href="https://github.com/rzwitserloot/lombok.patcher">lombok.patcher</a> project, published by
32+
* <a href="https://github.com/rzwitserloot">Reinier Zwitserloot</a>. An updated version of the original
33+
* code can be found <a
34+
* href="https://github.com/rzwitserloot/lombok.patcher/blob/master/src/patcher/lombok/patcher/ClassRootFinder.java">
35+
* here</a>.
2636
*/
2737
public class JarUtils {
2838

@@ -71,6 +81,10 @@ public static String getClasspath(final String[] dependencyContexts) {
7181
/**
7282
* If the provided class has been loaded from a JAR file that is on the
7383
* local file system, will find the absolute path to that JAR file.
84+
* <p>
85+
* <b>NOTE</b>: The core implementation of this method was lifted from
86+
* the {@code lombok.patcher} project. See the comments at the head of
87+
* {@link JarUtils this class} for details.
7488
*
7589
* @param contextClassName
7690
* The JAR file that contained the class file that represents
@@ -107,15 +121,13 @@ public static String findJarPathFor(final String contextClassName) {
107121
if (uri.endsWith(relPath)) {
108122
idx = uri.length() - relPath.length();
109123
} else {
110-
throw new IllegalStateException(
111-
"This class has been loaded from a class file, but I can't make sense of the path!");
124+
throw new IllegalStateException("Unrecognized structure file-protocol path: " + uri);
112125
}
113126
} else if (uri.startsWith("jar:file:")) {
114127
protocol = "jar:file:";
115128
idx = uri.indexOf('!');
116129
if (idx == -1) {
117-
throw new IllegalStateException(
118-
"You appear to have loaded this class from a local jar file, but I can't make sense of the URL!");
130+
throw new IllegalStateException("No separator found in jar-protocol path: " + uri);
119131
}
120132
} else {
121133
idx = uri.indexOf(':');

0 commit comments

Comments
 (0)