package com.github.ulisesbocchio.jar.resources;

import org.springframework.core.io.Resource;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;

/**
 * @author Ulises Bocchio
 */
public class JarResource implements Resource {

    private final Resource delegate;
    private final String extractPath;
    private File tempFile;

    public JarResource(Resource resource) {
        this(resource, null);

    }

    public JarResource(Resource resource, String extractPath) {
        this.delegate = resource;
        this.extractPath = extractPath;
    }

    @Override
    public boolean exists() {
        return delegate.exists();
    }

    @Override
    public boolean isReadable() {
        return delegate.isReadable();
    }

    @Override
    public boolean isOpen() {
        return delegate.isOpen();
    }

    @Override
    public URL getURL() throws IOException {
        return delegate.getURL();
    }

    @Override
    public URI getURI() throws IOException {
        return delegate.getURI();
    }

    @Override
    public File getFile() throws IOException {
        if(ResourceUtils.isJarURL(getURL())) {
            if(tempFile == null || !tempFile.exists()) {
                tempFile = JarUtils.getFile(delegate, extractPath);
            }
            return new File(tempFile.toURI());
        }
        return delegate.getFile();
    }

    @Override
    public long contentLength() throws IOException {
        return getFile().length();
    }

    @Override
    public long lastModified() throws IOException {
        return getFile().lastModified();
    }

    @Override
    public Resource createRelative(String relativePath) throws IOException {
        return new JarResource(delegate.createRelative(relativePath));
    }

    @Override
    public String getFilename() {
        return delegate.getFilename();
    }

    @Override
    public String getDescription() {
        return delegate.getDescription();
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return delegate.getInputStream();
    }

    /**
     * This implementation returns the description of this resource.
     * @see #getDescription()
     */
    @Override
    public String toString() {
        return getDescription();
    }

    /**
     * This implementation compares description strings.
     * @see #getDescription()
     */
    @Override
    public boolean equals(Object obj) {
        return (obj == this ||
                (obj instanceof Resource && ((Resource) obj).getDescription().equals(getDescription())));
    }

    /**
     * This implementation returns the description's hash code.
     * @see #getDescription()
     */
    @Override
    public int hashCode() {
        return getDescription().hashCode();
    }

}

@@ -38,24 +38,59 @@
 resources;%0A%0A
+import lombok.extern.slf4j.Slf4j;%0A%0A
 import org.s
@@ -288,16 +288,85 @@
 net.URL;
+%0Aimport java.util.Map;%0Aimport java.util.concurrent.ConcurrentHashMap;
 %0A%0A/**%0A *
@@ -393,16 +393,23 @@
 hio%0A */%0A
+@Slf4j%0A
 public c
@@ -539,21 +539,77 @@
 ate 
-File tempFile
+static final Map%3CURL, File%3E FILE_REGISTRY = new ConcurrentHashMap%3C%3E()
 ;%0A%0A 
@@ -1350,32 +1350,68 @@
 s IOException %7B%0A
+        URL resourceUrl = getURL();%0A
         if(Resou
@@ -1432,21 +1432,84 @@
 URL(
-getURL()
+resourceUrl
 )) %7B%0A
+            File tempFile = FILE_REGISTRY.get(resourceUrl);%0A
     
@@ -1581,57 +1581,285 @@
     
-tempFile = JarUtils.getFile(delegate, extractPath
+log.debug(%22Extracting File for URL: %7B%7D%22, resourceUrl);%0A                tempFile = JarUtils.getFile(delegate, extractPath);%0A                FILE_REGISTRY.put(resourceUrl, tempFile);%0A            %7D else %7B%0A                log.debug(%22File found in registry for URL: %7B%7D%22, resourceUrl
 );%0A 
@@ -2352,16 +2352,29 @@
 ivePath)
+, extractPath
 );%0A    %7D

Update JarResource.java