I have a single page application where the resources sit on the classpath. Any request for a resource that doesn't exist should redirect to the index.html
page. Resources should be mapped to memory on first request and then all subsequent requests should load from memory.
Have I made any mistakes with how I should be using direct ByteBuffers, it feels overly laborious, but that could just be the API?
class MemoryMappedClasspathHttpServlet extends HttpServlet {
private final ConcurrentMap<String, ByteBuffer> mappedResources = new ConcurrentHashMap<>();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String requestPath = req.getPathInfo();
if (requestPath.equals("/")) {
requestPath = "https://waybackassets.bk21.net/index.html";
} else {
requestPath = "/web" + requestPath;
if (MemoryMappedClasspathHttpServlet.class.getResource(requestPath) == null) {
requestPath = "https://waybackassets.bk21.net/index.html";
}
}
ByteBuffer buffer = mappedResources.computeIfAbsent(requestPath, MemoryMappedClasspathHttpServlet::loadResourceFromClasspath);
Channels.newChannel(resp.getOutputStream())
.write(buffer.duplicate());
}
private static ByteBuffer loadResourceFromClasspath(String classpathItem) {
try (ByteArrayOutputStream os = new ByteArrayOutputStream();
InputStream is = MemoryMappedClasspathHttpServlet.class.getResourceAsStream(classpathItem)) {
byte[] buffer = new byte[8092];
for (int len; (len = is.read(buffer)) != -1; ) {
os.write(buffer, 0, len);
}
os.flush();
byte[] bytes = os.toByteArray();
ByteBuffer directBuffer = ByteBuffer.allocateDirect(bytes.length);
directBuffer.put(bytes);
directBuffer.flip();
return directBuffer;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}