Skip to content

Commit ee53b6c

Browse files
committed
Update JarUtils.java
1 parent c2863e4 commit ee53b6c

1 file changed

Lines changed: 175 additions & 46 deletions

File tree

  • microsphere-java-core/src/main/java/io/microsphere/util/jar

microsphere-java-core/src/main/java/io/microsphere/util/jar/JarUtils.java

Lines changed: 175 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package io.microsphere.util.jar;
55

66
import io.microsphere.annotation.Nonnull;
7+
import io.microsphere.annotation.Nullable;
78
import io.microsphere.constants.ProtocolConstants;
89
import io.microsphere.filter.JarEntryFilter;
910
import io.microsphere.util.Utils;
@@ -51,12 +52,25 @@ public abstract class JarUtils implements Utils {
5152
public static final String MANIFEST_RESOURCE_PATH = "META-INF/MANIFEST.MF";
5253

5354
/**
54-
* Create a {@link JarFile} from specified {@link URL} of {@link JarFile}
55+
* Creates a {@link JarFile} from the specified {@link URL}.
5556
*
56-
* @param jarURL {@link URL} of {@link JarFile} or {@link JarEntry}
57-
* @return JarFile
58-
* @throws IOException If {@link JarFile jar file} is invalid, see {@link JarFile#JarFile(String)}
57+
* <p>
58+
* This method resolves the absolute path of the JAR file from the provided URL and constructs
59+
* a new {@link JarFile} instance. If the URL does not point to a valid JAR or file resource,
60+
* this method returns {@code null}.
61+
* </p>
62+
*
63+
* <h3>Example Usage</h3>
64+
* <pre>{@code
65+
* URL jarURL = new URL("jar:file:/path/to/file.jar!/entry");
66+
* JarFile jarFile = JarUtils.toJarFile(jarURL);
67+
* }</pre>
68+
*
69+
* @param jarURL the URL pointing to a JAR file or entry; must not be {@code null}
70+
* @return a new {@link JarFile} instance if resolved successfully, or {@code null} if resolution fails
71+
* @throws IOException if an I/O error occurs while creating the JAR file
5972
*/
73+
@Nullable
6074
public static JarFile toJarFile(URL jarURL) throws IOException {
6175
JarFile jarFile = null;
6276
final String jarAbsolutePath = resolveJarAbsolutePath(jarURL);
@@ -83,15 +97,26 @@ protected static void assertJarURLProtocol(URL jarURL) throws NullPointerExcepti
8397
}
8498
}
8599

100+
86101
/**
87-
* Resolve Relative path from Jar URL
102+
* Resolves the relative path from the given JAR URL.
88103
*
89-
* @param jarURL {@link URL} of {@link JarFile} or {@link JarEntry}
90-
* @return Non-null
91-
* @throws NullPointerException see {@link #assertJarURLProtocol(URL)}
92-
* @throws IllegalArgumentException see {@link #assertJarURLProtocol(URL)}
104+
* <p>This method extracts the part of the URL after the archive entry separator (e.g., "!/")
105+
* and decodes it to provide a normalized relative path within the JAR archive.</p>
106+
*
107+
* <h3>Example Usage</h3>
108+
* <pre>{@code
109+
* URL jarURL = new URL("jar:file:/path/to/file.jar!/com/example/resource.txt");
110+
* String relativePath = JarUtils.resolveRelativePath(jarURL);
111+
* System.out.println(relativePath); // Output: com/example/resource.txt
112+
* }</pre>
113+
*
114+
* @param jarURL the URL pointing to a resource within a JAR file; must not be {@code null}
115+
* @return the resolved relative path within the JAR archive
116+
* @throws NullPointerException if the provided {@code jarURL} is {@code null}
117+
* @throws IllegalArgumentException if the URL protocol is neither "jar" nor "file"
93118
*/
94-
@Nonnull
119+
@Nullable
95120
public static String resolveRelativePath(URL jarURL) throws NullPointerException, IllegalArgumentException {
96121
assertJarURLProtocol(jarURL);
97122
String form = jarURL.toExternalForm();
@@ -101,27 +126,49 @@ public static String resolveRelativePath(URL jarURL) throws NullPointerException
101126
}
102127

103128
/**
104-
* Resolve absolute path from the {@link URL} of {@link JarEntry}
129+
* Resolves the absolute path of the JAR file from the provided URL.
105130
*
106-
* @param jarURL {@link URL} of {@link JarFile} or {@link JarEntry}
107-
* @return If {@link URL#getProtocol()} equals <code>jar</code> or <code>file</code> , resolves absolute path, or
108-
* return <code>null</code>
109-
* @throws NullPointerException see {@link #assertJarURLProtocol(URL)}
110-
* @throws IllegalArgumentException see {@link #assertJarURLProtocol(URL)}
131+
* <p>
132+
* This method ensures that the URL protocol is either "jar" or "file", and then resolves
133+
* the absolute path to the corresponding JAR archive on the file system. If the URL does not
134+
* point to a valid JAR or file resource, this method returns {@code null}.
135+
* </p>
136+
*
137+
* <h3>Example Usage</h3>
138+
* <pre>{@code
139+
* URL jarURL = new URL("jar:file:/path/to/file.jar!/com/example/resource.txt");
140+
* String absolutePath = JarUtils.resolveJarAbsolutePath(jarURL);
141+
* System.out.println(absolutePath); // Output: /path/to/file.jar
142+
* }</pre>
143+
*
144+
* @param jarURL the URL pointing to a JAR file or entry; must not be {@code null}
145+
* @return the resolved absolute path of the JAR file if successful, or {@code null} if resolution fails
146+
* @throws NullPointerException if the provided {@code jarURL} is {@code null}
147+
* @throws IllegalArgumentException if the URL protocol is neither "jar" nor "file"
111148
*/
112-
@Nonnull
149+
@Nullable
113150
public static String resolveJarAbsolutePath(URL jarURL) throws NullPointerException, IllegalArgumentException {
114151
assertJarURLProtocol(jarURL);
115152
File archiveFile = resolveArchiveFile(jarURL);
116153
return archiveFile == null ? null : archiveFile.getAbsolutePath();
117154
}
118155

119156
/**
120-
* Filter {@link JarEntry} list from {@link JarFile}
157+
* Filters the entries of a JAR file based on the provided {@link JarEntryFilter}.
158+
*
159+
* <p>This method iterates through all entries in the given JAR file and applies the filter to selectively include
160+
* or exclude entries. If the provided {@link JarFile} is null or empty, an empty list is returned.</p>
121161
*
122-
* @param jarFile {@link JarFile}
123-
* @param jarEntryFilter {@link JarEntryFilter}
124-
* @return Read-only List
162+
* <h3>Example Usage</h3>
163+
* <pre>{@code
164+
* JarFile jarFile = new JarFile("example.jar");
165+
* JarEntryFilter classFileFilter = entry -> entry.getName().endsWith(".class");
166+
* List<JarEntry> filteredEntries = JarUtils.filter(jarFile, classFileFilter);
167+
* }</pre>
168+
*
169+
* @param jarFile The source JAR file; may be null.
170+
* @param jarEntryFilter The filter used to determine which entries to include; may be null (no filtering).
171+
* @return A read-only list of filtered JAR entries. Never null.
125172
*/
126173
@Nonnull
127174
public static List<JarEntry> filter(JarFile jarFile, JarEntryFilter jarEntryFilter) {
@@ -144,65 +191,147 @@ protected static List<JarEntry> doFilter(Iterable<JarEntry> jarEntries, JarEntry
144191
}
145192

146193
/**
147-
* Find {@link JarEntry} from specified <code>url</code>
194+
* Finds and returns the {@link JarEntry} from the specified JAR URL.
195+
*
196+
* <p>
197+
* This method resolves the relative path within the JAR archive from the provided URL and retrieves
198+
* the corresponding entry. If the entry does not exist or if there's an issue accessing the JAR file,
199+
* an exception may be thrown or a null value returned depending on underlying behavior.
200+
* </p>
148201
*
149-
* @param jarURL jar resource url
150-
* @return If found , return {@link JarEntry}
202+
* <h3>Example Usage</h3>
203+
* <pre>{@code
204+
* URL jarURL = new URL("jar:file:/path/to/file.jar!/com/example/resource.txt");
205+
* JarEntry jarEntry = JarUtils.findJarEntry(jarURL);
206+
* System.out.println(jarEntry.getName()); // Output: com/example/resource.txt
207+
* }</pre>
208+
*
209+
* @param jarURL the URL pointing to a resource within a JAR file; must not be {@code null}
210+
* @return the resolved {@link JarEntry} if found, or {@code null} if no such entry exists
211+
* @throws IOException if an I/O error occurs while reading the JAR file or resolving the entry
151212
*/
213+
@Nullable
152214
public static JarEntry findJarEntry(URL jarURL) throws IOException {
153215
JarFile jarFile = toJarFile(jarURL);
154216
final String relativePath = resolveRelativePath(jarURL);
155217
JarEntry jarEntry = jarFile.getJarEntry(relativePath);
156218
return jarEntry;
157219
}
158220

159-
160221
/**
161-
* Extract the source {@link JarFile} to target directory
222+
* Extracts the contents of the specified JAR file to the given target directory.
162223
*
163-
* @param jarSourceFile the source {@link JarFile}
164-
* @param targetDirectory target directory
165-
* @throws IOException When the source jar file is an invalid {@link JarFile}
224+
* <p>
225+
* This method extracts all entries from the provided JAR file into the target directory,
226+
* preserving the original directory structure. If the JAR file contains nested directories,
227+
* they will be recreated under the target directory.
228+
* </p>
229+
*
230+
* <h3>Example Usage</h3>
231+
* <pre>{@code
232+
* File jarFile = new File("example.jar");
233+
* File outputDir = new File("/path/to/output");
234+
* JarUtils.extract(jarFile, outputDir);
235+
* }</pre>
236+
*
237+
* @param jarSourceFile the source JAR file to extract; must not be {@code null}
238+
* @param targetDirectory the target directory where contents will be extracted; must not be {@code null}
239+
* @throws IOException if an I/O error occurs during extraction or if the provided file is not a valid JAR
166240
*/
167241
public static void extract(File jarSourceFile, File targetDirectory) throws IOException {
168242
extract(jarSourceFile, targetDirectory, null);
169243
}
170244

171245
/**
172-
* Extract the source {@link JarFile} to target directory with specified {@link JarEntryFilter}
246+
* Extracts the contents of the specified JAR file to the given target directory, optionally filtering entries.
247+
*
248+
* <p>
249+
* This method extracts entries from the provided JAR file into the target directory. If a filter is provided,
250+
* only entries accepted by the filter will be extracted. The original directory structure of the JAR is preserved
251+
* under the target directory.
252+
* </p>
253+
*
254+
* <h3>Example Usage</h3>
255+
* <pre>{@code
256+
* File jarFile = new File("example.jar");
257+
* File outputDir = new File("/path/to/output");
173258
*
174-
* @param jarSourceFile the source {@link JarFile}
175-
* @param targetDirectory target directory
176-
* @param jarEntryFilter {@link JarEntryFilter}
177-
* @throws IOException When the source jar file is an invalid {@link JarFile}
259+
* // Extract all entries
260+
* JarUtils.extract(jarFile, outputDir, null);
261+
*
262+
* // Extract only .class files
263+
* JarEntryFilter classFileFilter = entry -> entry.getName().endsWith(".class");
264+
* JarUtils.extract(jarFile, outputDir, classFileFilter);
265+
* }</pre>
266+
*
267+
* @param jarSourceFile the source JAR file to extract; must not be {@code null}
268+
* @param targetDirectory the target directory where contents will be extracted; must not be {@code null}
269+
* @param jarEntryFilter an optional filter to restrict which entries are extracted; may be {@code null} to extract all entries
270+
* @throws IOException if an I/O error occurs during extraction or if the provided file is not a valid JAR
178271
*/
179272
public static void extract(File jarSourceFile, File targetDirectory, JarEntryFilter jarEntryFilter) throws IOException {
180-
181273
final JarFile jarFile = new JarFile(jarSourceFile);
182-
183274
extract(jarFile, targetDirectory, jarEntryFilter);
184275
}
185276

186277
/**
187-
* Extract the source {@link JarFile} to target directory with specified {@link JarEntryFilter}
278+
* Extracts entries from a JAR file to the specified target directory, optionally filtering which entries to extract.
188279
*
189-
* @param jarFile the source {@link JarFile}
190-
* @param targetDirectory target directory
191-
* @param jarEntryFilter {@link JarEntryFilter}
192-
* @throws IOException When the source jar file is an invalid {@link JarFile}
280+
* <p>This method filters the entries in the JAR file using the provided {@link JarEntryFilter}, and extracts only those
281+
* entries that are accepted by the filter. If no filter is provided (i.e., {@code null}), all entries will be extracted.
282+
* The directory structure within the JAR is preserved under the target directory.</p>
283+
*
284+
* <h3>Example Usage</h3>
285+
* <pre>{@code
286+
* JarFile jarFile = new JarFile("example.jar");
287+
* File outputDir = new File("/path/to/output");
288+
*
289+
* // Extract all entries
290+
* JarUtils.extract(jarFile, outputDir, null);
291+
*
292+
* // Extract only .class files
293+
* JarEntryFilter classFileFilter = entry -> entry.getName().endsWith(".class");
294+
* JarUtils.extract(jarFile, outputDir, classFileFilter);
295+
* }</pre>
296+
*
297+
* @param jarFile the source JAR file to extract from; must not be {@code null}
298+
* @param targetDirectory the directory where the contents should be extracted; must not be {@code null}
299+
* @param jarEntryFilter an optional filter to determine which entries to extract; if {@code null}, all entries are extracted
300+
* @throws IOException if an I/O error occurs during extraction or if the JAR file is invalid
193301
*/
194302
public static void extract(JarFile jarFile, File targetDirectory, JarEntryFilter jarEntryFilter) throws IOException {
195303
List<JarEntry> jarEntriesList = filter(jarFile, jarEntryFilter);
196304
doExtract(jarFile, jarEntriesList, targetDirectory);
197305
}
198306

199307
/**
200-
* Extract the source {@link JarFile} to target directory with specified {@link JarEntryFilter}
308+
* Extracts entries from a JAR resource pointed by the given URL to the specified target directory,
309+
* optionally filtering which entries to extract.
310+
*
311+
* <p>
312+
* This method resolves the JAR file and relative path from the provided URL, filters the entries
313+
* using the given {@link JarEntryFilter}, and extracts them to the target directory while preserving
314+
* the original directory structure. If no filter is provided (i.e., {@code null}), all entries under
315+
* the resolved path will be extracted.
316+
* </p>
317+
*
318+
* <h3>Example Usage</h3>
319+
* <pre>{@code
320+
* URL jarURL = new URL("jar:file:/path/to/file.jar!/com/example/");
321+
* File outputDir = new File("/path/to/output");
322+
*
323+
* // Extract all entries under 'com/example/'
324+
* JarUtils.extract(jarURL, outputDir, null);
325+
*
326+
* // Extract only .class files under 'com/example/'
327+
* JarEntryFilter classFileFilter = entry -> entry.getName().endsWith(".class");
328+
* JarUtils.extract(jarURL, outputDir, classFileFilter);
329+
* }</pre>
201330
*
202-
* @param jarResourceURL The resource URL of {@link JarFile} or {@link JarEntry}
203-
* @param targetDirectory target directory
204-
* @param jarEntryFilter {@link JarEntryFilter}
205-
* @throws IOException When the source jar file is an invalid {@link JarFile}
331+
* @param jarResourceURL the URL pointing to a resource within a JAR file; must not be {@code null}
332+
* @param targetDirectory the directory where the contents should be extracted; must not be {@code null}
333+
* @param jarEntryFilter an optional filter to determine which entries to extract; if {@code null}, all entries are extracted
334+
* @throws IOException if an I/O error occurs during extraction or resolving the JAR resource
206335
*/
207336
public static void extract(URL jarResourceURL, File targetDirectory, JarEntryFilter jarEntryFilter) throws IOException {
208337
final JarFile jarFile = toJarFile(jarResourceURL);

0 commit comments

Comments
 (0)