Skip to content

Commit 82bd613

Browse files
committed
Resource utility.
1 parent b2dd08c commit 82bd613

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package com.falsepattern.lib.util;
2+
3+
import lombok.val;
4+
5+
import java.io.ByteArrayOutputStream;
6+
import java.io.FileNotFoundException;
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
import java.net.URL;
10+
import java.nio.charset.Charset;
11+
import java.nio.charset.StandardCharsets;
12+
13+
/**
14+
* A utility class for reading resources in many ways.
15+
*/
16+
public class ResourceUtil {
17+
18+
/**
19+
* Reads a resource as a string, using the {@link StandardCharsets#UTF_8} charset, from a specific jar file. See {@link #getResourceFromJar(String, Class)}.
20+
* @param resourcePath The resource to read
21+
* @param referenceClass The class, from whose jar to get the resource from
22+
* @return The string from the resource
23+
* @throws IOException From {@link #readBytes(InputStream)}
24+
*/
25+
public static String getResourceStringFromJar(String resourcePath, Class<?> referenceClass) throws IOException {
26+
return getResourceStringFromJar(resourcePath, referenceClass, StandardCharsets.UTF_8);
27+
}
28+
29+
30+
/**
31+
* Reads a resource as a string from a specific jar file. See {@link #getResourceFromJar(String, Class)}.
32+
* @param resourcePath The resource to read
33+
* @param referenceClass The class, from whose jar to get the resource from
34+
* @param charset The charset to decode the raw bytes with
35+
* @return The string from the resource
36+
* @throws IOException From {@link #readBytes(InputStream)}
37+
*/
38+
public static String getResourceStringFromJar(String resourcePath, Class<?> referenceClass, Charset charset) throws IOException {
39+
return new String(getResourceBytesFromJar(resourcePath, referenceClass), charset);
40+
}
41+
42+
43+
/**
44+
* Reads a resource as a string, using the {@link StandardCharsets#UTF_8} charset.
45+
* @param resourcePath The resource to read
46+
* @return The string from the resource
47+
* @throws IOException From {@link #readBytes(InputStream)}
48+
*/
49+
public static String getResourceString(String resourcePath) throws IOException {
50+
return getResourceString(resourcePath, StandardCharsets.UTF_8);
51+
}
52+
53+
/**
54+
* Reads a resource as a string.
55+
* @param resourcePath The resource to read
56+
* @param charset The charset to decode the raw bytes with
57+
* @return The string from the resource
58+
* @throws IOException From {@link #readBytes(InputStream)}
59+
*/
60+
public static String getResourceString(String resourcePath, Charset charset) throws IOException {
61+
return new String(getResourceBytes(resourcePath), charset);
62+
}
63+
64+
/**
65+
* Reads the raw bytes of a resource in a specific jar file. See {@link #getResourceFromJar(String, Class)}.
66+
* @param resourcePath The resource to read
67+
* @param referenceClass The class, from whose jar to get the resource from
68+
* @return The bytes of the resource
69+
* @throws IOException From {@link #readBytes(InputStream)}
70+
*/
71+
public static byte[] getResourceBytesFromJar(String resourcePath, Class<?> referenceClass) throws IOException {
72+
return readBytesSafe(getResourceFromJar(resourcePath, referenceClass), resourcePath);
73+
}
74+
75+
/**
76+
* Reads the raw bytes of a resource.
77+
* @param resourcePath The resource to read
78+
* @return The bytes of the resource
79+
* @throws IOException From {@link #readBytes(InputStream)}
80+
*/
81+
public static byte[] getResourceBytes(String resourcePath) throws IOException {
82+
return readBytesSafe(ResourceUtil.class.getResourceAsStream(resourcePath), resourcePath);
83+
}
84+
85+
private static byte[] readBytesSafe(InputStream stream, String resourcePath) throws IOException {
86+
if (stream == null) {
87+
throw new FileNotFoundException("Could not find resource at " + resourcePath);
88+
}
89+
return readBytes(stream);
90+
}
91+
92+
/**
93+
* Fully reads a stream into a byte array.
94+
* @param stream The stream to read
95+
* @return The data from the stream
96+
* @throws IOException From {@link InputStream#read(byte[])}
97+
*/
98+
public static byte[] readBytes(InputStream stream) throws IOException {
99+
val out = new ByteArrayOutputStream();
100+
val buf = new byte[4096];
101+
int read;
102+
while ((read = stream.read(buf)) >= 0) {
103+
out.write(buf, 0, read);
104+
}
105+
return out.toByteArray();
106+
}
107+
108+
/**
109+
* Retrieves a resource from the jar file of a specific class.
110+
* Falls back to {@link Class#getResourceAsStream(String)} if the resource is not found in the jar, or the class is
111+
* not from a jar file.
112+
* @param resourcePath The resource to retrieve
113+
* @param referenceClass The class, from whose jar to get the resource from
114+
* @return The resource, or null if it was not found.
115+
*/
116+
public static InputStream getResourceFromJar(String resourcePath, Class<?> referenceClass) {
117+
URL classFile = referenceClass.getResource('/' + referenceClass.getName().replace('.', '/') + ".class");
118+
lookup:
119+
{
120+
if (classFile == null)
121+
break lookup;
122+
String file = classFile.getFile();
123+
int id = file.indexOf("!");
124+
if (!classFile.getProtocol().equals("jar") || id < 0)
125+
break lookup;
126+
//Loading from a jar
127+
try {
128+
URL resource = new URL("jar:" + file.substring(0, id) + "!" + resourcePath);
129+
return resource.openStream();
130+
} catch (IOException e) {
131+
System.err.println("Failed to load resource " + resourcePath + " from jar " + file.substring(0, id));
132+
e.printStackTrace();
133+
}
134+
}
135+
//Fallback logic
136+
System.out.println("Using fallback resource loading logic for " + resourcePath + " with reference to " + referenceClass.getName());
137+
return referenceClass.getResourceAsStream(resourcePath);
138+
}
139+
}

0 commit comments

Comments
 (0)