diff --git a/booklore-api/src/main/java/com/adityachandel/booklore/service/metadata/parser/GoogleParser.java b/booklore-api/src/main/java/com/adityachandel/booklore/service/metadata/parser/GoogleParser.java index 0f680550..68c40028 100644 --- a/booklore-api/src/main/java/com/adityachandel/booklore/service/metadata/parser/GoogleParser.java +++ b/booklore-api/src/main/java/com/adityachandel/booklore/service/metadata/parser/GoogleParser.java @@ -35,6 +35,7 @@ public class GoogleParser implements BookParser { private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+"); private static final Pattern SPECIAL_CHARACTERS_PATTERN = Pattern.compile("[.,\\-\\[\\]{}()!@#$%^&*_=+|~`<>?/\";:]"); private final ObjectMapper objectMapper; + private final HttpClient httpClient = HttpClient.newHttpClient(); private static final String GOOGLE_BOOKS_API_URL = "https://www.googleapis.com/books/v1/volumes"; @Override @@ -61,13 +62,12 @@ public class GoogleParser implements BookParser { log.info("Google Books API URL (ISBN): {}", uri); - HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(uri) .GET() .build(); - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == 200) { return parseGoogleBooksApiResponse(response.body()); @@ -91,13 +91,12 @@ public class GoogleParser implements BookParser { log.info("Google Books API URL: {}", uri); - HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(uri) .GET() .build(); - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == 200) { return parseGoogleBooksApiResponse(response.body()); diff --git a/booklore-api/src/main/java/com/adityachandel/booklore/service/metadata/writer/EpubMetadataWriter.java b/booklore-api/src/main/java/com/adityachandel/booklore/service/metadata/writer/EpubMetadataWriter.java index 0bfe22f5..8ced7225 100644 --- a/booklore-api/src/main/java/com/adityachandel/booklore/service/metadata/writer/EpubMetadataWriter.java +++ b/booklore-api/src/main/java/com/adityachandel/booklore/service/metadata/writer/EpubMetadataWriter.java @@ -55,8 +55,9 @@ public class EpubMetadataWriter implements MetadataWriter { Path tempDir = null; try { tempDir = Files.createTempDirectory("epub_edit_" + UUID.randomUUID()); - ZipFile zipFile = new ZipFile(epubFile); - zipFile.extractAll(tempDir.toString()); + try (ZipFile zipFile = new ZipFile(epubFile)) { + zipFile.extractAll(tempDir.toString()); + } File opfFile = findOpfFile(tempDir.toFile()); if (opfFile == null) { @@ -171,7 +172,9 @@ public class EpubMetadataWriter implements MetadataWriter { transformer.transform(new DOMSource(opfDoc), new StreamResult(opfFile)); File tempEpub = new File(epubFile.getParentFile(), epubFile.getName() + ".tmp"); - addFolderContentsToZip(new ZipFile(tempEpub), tempDir.toFile(), tempDir.toFile()); + try (ZipFile tempZipFile = new ZipFile(tempEpub)) { + addFolderContentsToZip(tempZipFile, tempDir.toFile(), tempDir.toFile()); + } if (!epubFile.delete()) throw new IOException("Could not delete original EPUB"); if (!tempEpub.renameTo(epubFile)) throw new IOException("Could not rename temp EPUB"); @@ -260,7 +263,9 @@ public class EpubMetadataWriter implements MetadataWriter { try { File epubFile = new File(bookEntity.getFullFilePath().toUri()); tempDir = Files.createTempDirectory("epub_cover_" + UUID.randomUUID()); - new ZipFile(epubFile).extractAll(tempDir.toString()); + try (ZipFile zipFile = new ZipFile(epubFile)) { + zipFile.extractAll(tempDir.toString()); + } File opfFile = findOpfFile(tempDir.toFile()); if (opfFile == null) { @@ -282,7 +287,9 @@ public class EpubMetadataWriter implements MetadataWriter { transformer.transform(new DOMSource(opfDoc), new StreamResult(opfFile)); File tempEpub = new File(epubFile.getParentFile(), epubFile.getName() + ".tmp"); - addFolderContentsToZip(new ZipFile(tempEpub), tempDir.toFile(), tempDir.toFile()); + try (ZipFile tempZipFile = new ZipFile(tempEpub)) { + addFolderContentsToZip(tempZipFile, tempDir.toFile(), tempDir.toFile()); + } if (!epubFile.delete()) throw new IOException("Could not delete original EPUB"); if (!tempEpub.renameTo(epubFile)) throw new IOException("Could not rename temp EPUB"); @@ -308,7 +315,9 @@ public class EpubMetadataWriter implements MetadataWriter { try { File epubFile = new File(bookEntity.getFullFilePath().toUri()); tempDir = Files.createTempDirectory("epub_cover_url_" + UUID.randomUUID()); - new ZipFile(epubFile).extractAll(tempDir.toString()); + try (ZipFile zipFile = new ZipFile(epubFile)) { + zipFile.extractAll(tempDir.toString()); + } File opfFile = findOpfFile(tempDir.toFile()); if (opfFile == null) { @@ -335,7 +344,9 @@ public class EpubMetadataWriter implements MetadataWriter { transformer.transform(new DOMSource(opfDoc), new StreamResult(opfFile)); File tempEpub = new File(epubFile.getParentFile(), epubFile.getName() + ".tmp"); - addFolderContentsToZip(new ZipFile(tempEpub), tempDir.toFile(), tempDir.toFile()); + try (ZipFile tempZipFile = new ZipFile(tempEpub)) { + addFolderContentsToZip(tempZipFile, tempDir.toFile(), tempDir.toFile()); + } if (!epubFile.delete()) throw new IOException("Could not delete original EPUB"); if (!tempEpub.renameTo(epubFile)) throw new IOException("Could not rename temp EPUB"); diff --git a/booklore-api/src/main/java/com/adityachandel/booklore/service/migration/AppMigrationService.java b/booklore-api/src/main/java/com/adityachandel/booklore/service/migration/AppMigrationService.java index 078689c2..3989ad1f 100644 --- a/booklore-api/src/main/java/com/adityachandel/booklore/service/migration/AppMigrationService.java +++ b/booklore-api/src/main/java/com/adityachandel/booklore/service/migration/AppMigrationService.java @@ -127,46 +127,48 @@ public class AppMigrationService { try { if (Files.exists(thumbsDir)) { - Files.walk(thumbsDir) - .filter(Files::isRegularFile) - .forEach(path -> { - try { - // Load original image - BufferedImage originalImage = ImageIO.read(path.toFile()); - if (originalImage == null) { - log.warn("Skipping non-image file: {}", path); - return; + try (var stream = Files.walk(thumbsDir)) { + stream.filter(Files::isRegularFile) + .forEach(path -> { + try { + // Load original image + BufferedImage originalImage = ImageIO.read(path.toFile()); + if (originalImage == null) { + log.warn("Skipping non-image file: {}", path); + return; + } + + // Extract bookId from folder structure + Path relative = thumbsDir.relativize(path); // e.g., "11/f.jpg" + String bookId = relative.getParent().toString(); // "11" + + Path bookDir = imagesDir.resolve(bookId); + Files.createDirectories(bookDir); + + // Copy original to cover.jpg + Path coverFile = bookDir.resolve("cover.jpg"); + ImageIO.write(originalImage, "jpg", coverFile.toFile()); + + // Resize and save thumbnail.jpg + BufferedImage resized = fileService.resizeImage(originalImage, 250, 350); + Path thumbnailFile = bookDir.resolve("thumbnail.jpg"); + ImageIO.write(resized, "jpg", thumbnailFile.toFile()); + + log.debug("Processed book {}: cover={} thumbnail={}", bookId, coverFile, thumbnailFile); + } catch (IOException e) { + log.error("Error processing file {}", path, e); + throw new UncheckedIOException(e); } - - // Extract bookId from folder structure - Path relative = thumbsDir.relativize(path); // e.g., "11/f.jpg" - String bookId = relative.getParent().toString(); // "11" - - Path bookDir = imagesDir.resolve(bookId); - Files.createDirectories(bookDir); - - // Copy original to cover.jpg - Path coverFile = bookDir.resolve("cover.jpg"); - ImageIO.write(originalImage, "jpg", coverFile.toFile()); - - // Resize and save thumbnail.jpg - BufferedImage resized = fileService.resizeImage(originalImage, 250, 350); - Path thumbnailFile = bookDir.resolve("thumbnail.jpg"); - ImageIO.write(resized, "jpg", thumbnailFile.toFile()); - - log.debug("Processed book {}: cover={} thumbnail={}", bookId, coverFile, thumbnailFile); - } catch (IOException e) { - log.error("Error processing file {}", path, e); - throw new UncheckedIOException(e); - } - }); + }); + } // Delete old thumbs directory log.info("Deleting old thumbs directory: {}", thumbsDir); - Files.walk(thumbsDir) - .sorted(Comparator.reverseOrder()) - .map(Path::toFile) - .forEach(File::delete); + try (var stream = Files.walk(thumbsDir)) { + stream.sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + } } } catch (IOException e) { log.error("Error during migration populateCoversAndResizeThumbnails", e);