package org.lodder.subtools.sublibrary.cache;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.lodder.subtools.sublibrary.logging.Logger;

public class DiskCache<K, T> extends InMemoryCache<K, T> {

  private Connection conn;

  public DiskCache(long crunchifyTimeToLive, long crunchifyTimerInterval, int maxItems,
      String username, String password) {
    super(crunchifyTimeToLive, crunchifyTimerInterval, maxItems);
    File path = new File(System.getProperty("user.home"), ".MultiSubDownloader");
    if (!path.exists()) {
      if (!path.mkdir()) {
        throw new RuntimeException("Could not create folder " + path);
      }
    }
    try {
      Class.forName("org.hsqldb.jdbcDriver");
      conn =
          DriverManager.getConnection("jdbc:hsqldb:file:" + path.toString()
              + "/diskcache.hsqldb;hsqldb.write_delay=false;shutdown=true", username, password);

      PreparedStatement prep =
          conn.prepareStatement("create table IF NOT EXISTS cacheobjects (key OTHER, cacheobject OTHER);");
      prep.execute();
      prep.close();
      fillCacheMap();
    } catch (ClassNotFoundException e) {
      throw new RuntimeException("Unable to load jdbcdriver for diskcache");
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  @SuppressWarnings("unchecked")
  private void fillCacheMap() {
    try (Statement stmt = conn.createStatement()) {
      ResultSet rs = stmt.executeQuery("SELECT key, cacheobject FROM cacheobjects");
      while (rs.next()) {
        cacheMap.put(rs.getObject("key"), rs.getObject("cacheobject"));
      }
      rs.close();
    } catch (SQLException e) {
      Logger.instance.error("Unable to insert object in disk cache!");
    } finally {

    }
  }

  public void remove(K key) {
    super.remove(key);
    try (PreparedStatement prep = conn.prepareCall("delete from cacheobjects where key = ?")) {
      prep.clearParameters();
      prep.setObject(1, key);
      prep.execute();
    } catch (SQLException e) {
      Logger.instance.error("Unable to delete object from disk cache!");
    }
  }

  public void put(K key, T value) {
    super.put(key, value);
    try (PreparedStatement prep =
        conn.prepareCall("INSERT INTO cacheobjects (key,cacheobject) VALUES (?,?)")) {
      prep.clearParameters();
      prep.setObject(1, key);
      CacheObject<?, ?> cacheObject = (CacheObject<?, ?>) cacheMap.get(key);
      prep.setObject(2, cacheObject);
      prep.execute();
    } catch (SQLException e) {
      Logger.instance.error("Unable to insert object in disk cache!");
    }
  }
}

@@ -795,24 +795,59 @@
     %7D%0A    %7D%0A
+    PreparedStatement prep = null;%0A
     try %7B%0A  
@@ -844,16 +844,16 @@
   try %7B%0A
-
       Cl
@@ -1083,34 +1083,16 @@
 %0A%0A      
-PreparedStatement 
 prep =%0A 
@@ -1403,32 +1403,32 @@
 LException e) %7B%0A
-
       throw new 
@@ -1444,24 +1444,172 @@
 ception(e);%0A
+    %7D finally %7B%0A      try %7B%0A        if (prep != null) prep.close();%0A      %7D catch (SQLException e) %7B%0A        throw new RuntimeException(e);%0A      %7D%0A
     %7D%0A  %7D%0A%0A 

Fix possible resource leak