Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed image-loader, recreating images when file changes #50

Merged
merged 3 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,10 @@ public ImageEncoder getEncoder() {

/**
* Computes and returns a hash string representation for this instance.
* Note: This method currently returns the default hashCode as a string, which might not guarantee uniqueness.
*
* @return A string representing the hash of this instance.
*/
String getHashString() {
return Integer.toString(hashCode());
return ImageManager.computeImageDefinitionHash(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ CompletableFuture<Image> loadFXImageFuture(ImageSource source, ImageTransformer
* @param imageDefinition the image definition
* @return the computed MD5 hash as a string
*/
private String computeImageDefinitionHash(ImageDefinition imageDefinition) {
public static String computeImageDefinitionHash(ImageDefinition imageDefinition) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] hashBytes = digest.digest(imageDefinition.toJSON().toString().getBytes(StandardCharsets.UTF_8));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public JSONObject toJSON() {
JSONObject json = new JSONObject();
json.put("type", getClass().getSimpleName());
json.put("path", ImageUtils.escapeJson(file.getAbsolutePath()));
json.put("modified", file.lastModified());
return json;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,19 @@ public long identityHashValue() {
public JSONObject toJSON() {
JSONObject json = new JSONObject();
json.put("type", getClass().getSimpleName());
// Escaping might be necessary depending on the structure of resourcePath.
json.put("resourcePath", ImageUtils.escapeJson(resourcePath));
// get last modified date
// It's important, so the images get recreated, when the files in the jar are updated
try {
URL resourceUrl = getClass().getResource(resourcePath);
if (resourceUrl != null) {
// we don't access any stream here, so we don't need to close it
URLConnection conn = resourceUrl.openConnection();
json.put("modified", conn.getLastModified());
}
} catch (Exception ex) {
throw new RuntimeException("Error obtaining modification date for resource: " + resourcePath, ex);
}
return json;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import java.io.IOException;
import java.nio.file.Files;

import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;

Expand All @@ -26,6 +32,9 @@ class ImageManagerTest {

ImageManager manager;
ImageDefinition def;
File imageDef2File;
ImageDefinition imageDef2;



@BeforeEach
Expand All @@ -44,6 +53,12 @@ void setUp() throws InterruptedException {
ImageTransformer transformer = new ImageTransformerFitWidth(200);
ImageEncoder encoder = new ImageEncoderPNG();
def = new ImageDefinition(source, transformer, encoder);

imageDef2File = new File("testImage.png");
ImageSource source2 = new ImageSourceFile(imageDef2File);
ImageTransformer transformer2 = new ImageTransformerFitWidth(200);
ImageEncoder encoder2 = new ImageEncoderPNG();
imageDef2 = new ImageDefinition(source2, transformer2, encoder2);
}

@Test
Expand All @@ -68,6 +83,45 @@ void testImageNotCreatedTwice() {
assertEquals(imageFileBefore.lastModified(), imageFileAfter.lastModified(), "Image was created again.");
}

@Test
void testImageRecreateOnChange() throws IOException {
// Copy file1 to imageDef2File
File file1 = new File(getClass().getResource("/testImage.png").getFile());
File file2 = new File(getClass().getResource("/logo.png").getFile());
assertTrue(file1.exists());
assertTrue(file2.exists());

Files.copy(file1.toPath(), imageDef2File.toPath(), StandardCopyOption.REPLACE_EXISTING);

var image1 = manager.loadImage(imageDef2);
String hash1 = imageDef2.getHashString();
System.out.println("ModifiedDate1: " + imageDef2File.lastModified());

Files.copy(file2.toPath(), imageDef2File.toPath(), StandardCopyOption.REPLACE_EXISTING);
System.out.println("ModifiedDate2: " + imageDef2File.lastModified());
Files.setLastModifiedTime(imageDef2File.toPath(), FileTime.from(Instant.now()));
System.out.println("ModifiedDate3: " + imageDef2File.lastModified());

var image2 = manager.loadImage(imageDef2);
String hash2 = imageDef2.getHashString();

System.out.println("hash1: " + hash1);
System.out.println("hash2: " + hash2);
assertNotEquals(hash1, hash2, "changed image file should have different hash");

File imageFile1 = image1.getFile();
File imageFile2 = image2.getFile();

assertTrue(imageFile1.exists());
assertTrue(imageFile2.exists());

System.out.println("imageFile1: " + imageFile1.lastModified());
System.out.println("imageFile2: " + imageFile2.lastModified());

assertNotEquals(imageFile1.lastModified(), imageFile2.lastModified(),
"Image was not created again.");
}

@Test
void testLoadImageFuture() {
CompletableFuture<ImageResult> future = manager.loadImageFuture(def);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public void testToJson() {
JSONObject json = new JSONObject();
json.put("type", "ImageSourceFile");
json.put("path", ImageUtils.escapeJson(testImageFile.getAbsolutePath()));
json.put("modified", testImageFile.lastModified());

assertTrue(imageSource.toJSON().similar(json));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import org.junit.jupiter.api.Test;

import java.awt.image.BufferedImage;
import java.net.URL;
import java.net.URLConnection;

import static org.junit.jupiter.api.Assertions.*;

Expand All @@ -30,12 +32,18 @@ void testIdentityHashValue_validResourcePath_returnsHash() {
}

@Test
void testToJson_returnsExpectedJson() {
void testToJson_returnsExpectedJson() throws Exception {
ImageSourceResource resource = new ImageSourceResource("/testImage.png");

JSONObject json = new JSONObject();
json.put("type", "ImageSourceResource");
json.put("resourcePath", "/testImage.png");
URL resourceUrl = getClass().getResource("/testImage.png");
if (resourceUrl != null) {
// we don't access any stream here, so we don't need to close it
URLConnection conn = resourceUrl.openConnection();
json.put("modified", conn.getLastModified());
}
assertTrue(resource.toJSON().similar(json));
}
}
Loading