]> git.basschouten.com Git - openhab-addons.git/commitdiff
Replace 'ByteArrayFileCache' by OHC class (#8774)
authorChristoph Weitkamp <github@christophweitkamp.de>
Tue, 27 Oct 2020 23:21:52 +0000 (00:21 +0100)
committerGitHub <noreply@github.com>
Tue, 27 Oct 2020 23:21:52 +0000 (00:21 +0100)
Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
12 files changed:
bundles/org.openhab.binding.chromecast/src/main/java/org/openhab/binding/chromecast/internal/ChromecastStatusUpdater.java
bundles/org.openhab.binding.chromecast/src/main/java/org/openhab/binding/chromecast/internal/utils/ByteArrayFileCache.java [deleted file]
bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/connection/DarkSkyConnection.java
bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/utils/ByteArrayFileCache.java [deleted file]
bundles/org.openhab.binding.darksky/src/test/java/org/openhab/binding/darksky/internal/utils/ByteArrayFileCacheTest.java [deleted file]
bundles/org.openhab.binding.darksky/src/test/resources/sounds/doorbell.mp3 [deleted file]
bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiConnection.java
bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/utils/ByteArrayFileCache.java [deleted file]
bundles/org.openhab.binding.kodi/src/test/java/org/openhab/binding/kodi/internal/utils/ByteArrayFileCacheTest.java [deleted file]
bundles/org.openhab.binding.kodi/src/test/resources/sounds/doorbell.mp3 [deleted file]
bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/connection/OpenWeatherMapConnection.java
bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/utils/ByteArrayFileCache.java [deleted file]

index a293e50538ef1b1cb08539a9468792ef56cde689..61a1f24edecd1df3ee80557a0c29de920918e1e5 100644 (file)
@@ -26,7 +26,7 @@ import java.util.Map;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.chromecast.internal.handler.ChromecastHandler;
-import org.openhab.binding.chromecast.internal.utils.ByteArrayFileCache;
+import org.openhab.core.cache.ByteArrayFileCache;
 import org.openhab.core.io.net.http.HttpUtil;
 import org.openhab.core.library.types.DateTimeType;
 import org.openhab.core.library.types.DecimalType;
@@ -63,6 +63,7 @@ import su.litvak.chromecast.api.v2.Volume;
  */
 @NonNullByDefault
 public class ChromecastStatusUpdater {
+
     private final Logger logger = LoggerFactory.getLogger(ChromecastStatusUpdater.class);
 
     private final Thing thing;
diff --git a/bundles/org.openhab.binding.chromecast/src/main/java/org/openhab/binding/chromecast/internal/utils/ByteArrayFileCache.java b/bundles/org.openhab.binding.chromecast/src/main/java/org/openhab/binding/chromecast/internal/utils/ByteArrayFileCache.java
deleted file mode 100644 (file)
index da8bc59..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/**
- * Copyright (c) 2010-2020 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.chromecast.internal.utils;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.OpenHAB;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This is a simple file based cache implementation.
- *
- * @author Christoph Weitkamp - Initial contribution
- */
-@NonNullByDefault
-public class ByteArrayFileCache {
-
-    private final Logger logger = LoggerFactory.getLogger(ByteArrayFileCache.class);
-
-    private static final String MD5_ALGORITHM = "MD5";
-
-    static final String CACHE_FOLDER_NAME = "cache";
-    private static final char EXTENSION_SEPARATOR = '.';
-    private static final char UNIX_SEPARATOR = '/';
-    private static final char WINDOWS_SEPARATOR = '\\';
-
-    private final File cacheFolder;
-
-    static final long ONE_DAY_IN_MILLIS = TimeUnit.DAYS.toMillis(1);
-    private int expiry = 0;
-
-    private static final Map<String, File> FILES_IN_CACHE = new ConcurrentHashMap<>();
-
-    /**
-     * Creates a new {@link ByteArrayFileCache} instance for a service. Creates a <code>cache</code> folder under
-     * <code>$userdata/cache/$servicePID</code>.
-     *
-     * @param servicePID PID of the service
-     */
-    public ByteArrayFileCache(String servicePID) {
-        // TODO track and limit folder size
-        // TODO support user specific folder
-        cacheFolder = new File(new File(OpenHAB.getUserDataFolder(), CACHE_FOLDER_NAME), servicePID);
-        if (!cacheFolder.exists()) {
-            logger.debug("Creating cache folder '{}'", cacheFolder.getAbsolutePath());
-            cacheFolder.mkdirs();
-        }
-        logger.debug("Using cache folder '{}'", cacheFolder.getAbsolutePath());
-    }
-
-    /**
-     * Creates a new {@link ByteArrayFileCache} instance for a service. Creates a <code>cache</code> folder under
-     * <code>$userdata/cache/$servicePID/</code>.
-     *
-     * @param servicePID PID of the service
-     * @param int the days for how long the files stay in the cache valid. Must be positive. 0 to
-     *            disables this functionality.
-     */
-    public ByteArrayFileCache(String servicePID, int expiry) {
-        this(servicePID);
-        if (expiry < 0) {
-            throw new IllegalArgumentException("Cache expiration time must be greater than or equal to 0");
-        }
-        this.expiry = expiry;
-    }
-
-    /**
-     * Adds a file to the cache. If the cache previously contained a file for the key, the old file is replaced by the
-     * new content.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     */
-    public void put(String key, byte[] content) {
-        writeFile(getUniqueFile(key), content);
-    }
-
-    /**
-     * Adds a file to the cache.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     */
-    public void putIfAbsent(String key, byte[] content) {
-        File fileInCache = getUniqueFile(key);
-        if (fileInCache.exists()) {
-            logger.debug("File '{}' present in cache", fileInCache.getName());
-            // update time of last use
-            fileInCache.setLastModified(System.currentTimeMillis());
-        } else {
-            writeFile(fileInCache, content);
-        }
-    }
-
-    /**
-     * Adds a file to the cache and returns the content of the file.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     * @return the content of the file associated with the given key
-     */
-    public byte[] putIfAbsentAndGet(String key, byte[] content) {
-        putIfAbsent(key, content);
-
-        return content;
-    }
-
-    /**
-     * Writes the given content to the given {@link File}.
-     *
-     * @param fileInCache the {@link File}
-     * @param content the content to be written
-     */
-    private void writeFile(File fileInCache, byte[] content) {
-        logger.debug("Caching file '{}'", fileInCache.getName());
-        try {
-            Files.write(fileInCache.toPath(), content);
-        } catch (IOException e) {
-            logger.warn("Could not write file '{}' to cache", fileInCache.getName(), e);
-        }
-    }
-
-    /**
-     * Checks if the key is present in the cache.
-     *
-     * @param key the key whose presence in the cache is to be tested
-     * @return true if the cache contains a file for the specified key
-     */
-    public boolean containsKey(String key) {
-        return getUniqueFile(key).exists();
-    }
-
-    /**
-     * Removes the file associated with the given key from the cache.
-     *
-     * @param key the key whose associated file is to be removed
-     */
-    public void remove(String key) {
-        deleteFile(getUniqueFile(key));
-    }
-
-    /**
-     * Deletes the given {@link File}.
-     *
-     * @param fileInCache the {@link File}
-     */
-    private void deleteFile(File fileInCache) {
-        if (fileInCache.exists()) {
-            logger.debug("Deleting file '{}' from cache", fileInCache.getName());
-            fileInCache.delete();
-        } else {
-            logger.debug("File '{}' not found in cache", fileInCache.getName());
-        }
-    }
-
-    /**
-     * Removes all files from the cache.
-     */
-    public void clear() {
-        File[] filesInCache = cacheFolder.listFiles();
-        if (filesInCache != null && filesInCache.length > 0) {
-            logger.debug("Deleting all files from cache");
-            Arrays.stream(filesInCache).forEach(File::delete);
-        }
-    }
-
-    /**
-     * Removes expired files from the cache.
-     */
-    public void clearExpired() {
-        // exit if expiry is set to 0 (disabled)
-        if (expiry <= 0) {
-            return;
-        }
-        File[] filesInCache = cacheFolder.listFiles();
-        if (filesInCache != null && filesInCache.length > 0) {
-            logger.debug("Deleting expired files from cache");
-            Arrays.stream(filesInCache).filter(file -> isExpired(file)).forEach(File::delete);
-        }
-    }
-
-    /**
-     * Checks if the given {@link File} is expired.
-     *
-     * @param fileInCache the {@link File}
-     * @return <code>true</code> if the file is expired, <code>false</code> otherwise
-     */
-    private boolean isExpired(File fileInCache) {
-        // exit if expiry is set to 0 (disabled)
-        if (expiry <= 0) {
-            return false;
-        }
-        return expiry * ONE_DAY_IN_MILLIS < System.currentTimeMillis() - fileInCache.lastModified();
-    }
-
-    /**
-     * Returns the content of the file associated with the given key, if it is present.
-     *
-     * @param key the key whose associated file is to be returned
-     * @return the content of the file associated with the given key
-     * @throws FileNotFoundException if the given file could not be found in cache
-     * @throws IOException if an I/O error occurs reading the given file
-     */
-    public byte[] get(String key) throws FileNotFoundException, IOException {
-        return readFile(getUniqueFile(key));
-    }
-
-    /**
-     * Reads the content from the given {@link File}, if it is present.
-     *
-     * @param fileInCache the {@link File}
-     * @return the content of the file
-     * @throws FileNotFoundException if the given file could not be found in cache
-     * @throws IOException if an I/O error occurs reading the given file
-     */
-    private byte[] readFile(File fileInCache) throws FileNotFoundException, IOException {
-        if (fileInCache.exists()) {
-            logger.debug("Reading file '{}' from cache", fileInCache.getName());
-            // update time of last use
-            fileInCache.setLastModified(System.currentTimeMillis());
-            try {
-                return Files.readAllBytes(fileInCache.toPath());
-            } catch (IOException e) {
-                logger.warn("Could not read file '{}' from cache", fileInCache.getName(), e);
-                throw new IOException(String.format("Could not read file '%s' from cache", fileInCache.getName()));
-            }
-        } else {
-            logger.debug("File '{}' not found in cache", fileInCache.getName());
-            throw new FileNotFoundException(String.format("File '%s' not found in cache", fileInCache.getName()));
-        }
-    }
-
-    /**
-     * Creates a unique {@link File} from the key with which the file is to be associated.
-     *
-     * @param key the key with which the file is to be associated
-     * @return unique file for the file associated with the given key
-     */
-    File getUniqueFile(String key) {
-        String uniqueFileName = getUniqueFileName(key);
-        if (FILES_IN_CACHE.containsKey(uniqueFileName)) {
-            return FILES_IN_CACHE.get(uniqueFileName);
-        } else {
-            String fileExtension = getFileExtension(key);
-            File fileInCache = new File(cacheFolder,
-                    uniqueFileName + (fileExtension == null ? "" : EXTENSION_SEPARATOR + fileExtension));
-            FILES_IN_CACHE.put(uniqueFileName, fileInCache);
-            return fileInCache;
-        }
-    }
-
-    /**
-     * Gets the extension of a file name.
-     *
-     * @param fileName the file name to retrieve the extension of
-     * @return the extension of the file or null if none exists
-     */
-    @Nullable
-    String getFileExtension(String fileName) {
-        int extensionPos = fileName.lastIndexOf(EXTENSION_SEPARATOR);
-        int lastSeparatorPos = Math.max(fileName.lastIndexOf(UNIX_SEPARATOR), fileName.lastIndexOf(WINDOWS_SEPARATOR));
-        return lastSeparatorPos > extensionPos ? null : fileName.substring(extensionPos + 1).replaceFirst("\\?.*$", "");
-    }
-
-    /**
-     * Creates a unique file name from the key with which the file is to be associated.
-     *
-     * @param key the key with which the file is to be associated
-     * @return unique file name for the file associated with the given key
-     */
-    String getUniqueFileName(String key) {
-        try {
-            final MessageDigest md = MessageDigest.getInstance(MD5_ALGORITHM);
-            return String.format("%032x", new BigInteger(1, md.digest(key.getBytes(StandardCharsets.UTF_8))));
-        } catch (NoSuchAlgorithmException ex) {
-            // should not happen
-            logger.error("Could not create MD5 hash for key '{}'", key, ex);
-            return key;
-        }
-    }
-}
index ba7f3951cb9cd22b51cb7d817594734442e0bd53..5adbe8ce3b9eb828a8f2d0135a992e1f0dcb3cde 100644 (file)
@@ -16,6 +16,7 @@ import static java.util.stream.Collectors.joining;
 import static org.eclipse.jetty.http.HttpMethod.GET;
 import static org.eclipse.jetty.http.HttpStatus.*;
 
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
@@ -34,7 +35,7 @@ import org.eclipse.jetty.client.api.ContentResponse;
 import org.openhab.binding.darksky.internal.config.DarkSkyAPIConfiguration;
 import org.openhab.binding.darksky.internal.handler.DarkSkyAPIHandler;
 import org.openhab.binding.darksky.internal.model.DarkSkyJsonWeatherData;
-import org.openhab.binding.darksky.internal.utils.ByteArrayFileCache;
+import org.openhab.core.cache.ByteArrayFileCache;
 import org.openhab.core.cache.ExpiringCacheMap;
 import org.openhab.core.io.net.http.HttpUtil;
 import org.openhab.core.library.types.PointType;
@@ -126,7 +127,12 @@ public class DarkSkyConnection {
 
     private static @Nullable RawType downloadWeatherIconFromCache(String url) {
         if (IMAGE_CACHE.containsKey(url)) {
-            return new RawType(IMAGE_CACHE.get(url), PNG_CONTENT_TYPE);
+            try {
+                return new RawType(IMAGE_CACHE.get(url), PNG_CONTENT_TYPE);
+            } catch (IOException e) {
+                LoggerFactory.getLogger(DarkSkyConnection.class).trace("Failed to download the content of URL '{}'",
+                        url, e);
+            }
         } else {
             RawType image = downloadWeatherIcon(url);
             if (image != null) {
diff --git a/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/utils/ByteArrayFileCache.java b/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/utils/ByteArrayFileCache.java
deleted file mode 100644 (file)
index 2bc89ff..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/**
- * Copyright (c) 2010-2020 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.darksky.internal.utils;
-
-import java.io.File;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.OpenHAB;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This is a simple file based cache implementation.
- *
- * @author Christoph Weitkamp - Initial contribution
- */
-@NonNullByDefault
-public class ByteArrayFileCache {
-
-    private final Logger logger = LoggerFactory.getLogger(ByteArrayFileCache.class);
-
-    private static final String MD5_ALGORITHM = "MD5";
-
-    static final String CACHE_FOLDER_NAME = "cache";
-    private static final char EXTENSION_SEPARATOR = '.';
-    private static final char UNIX_SEPARATOR = '/';
-    private static final char WINDOWS_SEPARATOR = '\\';
-
-    private final File cacheFolder;
-
-    static final long ONE_DAY_IN_MILLIS = TimeUnit.DAYS.toMillis(1);
-    private int expiry = 0;
-
-    private static final Map<String, File> FILES_IN_CACHE = new ConcurrentHashMap<>();
-
-    /**
-     * Creates a new {@link ByteArrayFileCache} instance for a service. Creates a <code>cache</code> folder under
-     * <code>$userdata/cache/$servicePID</code>.
-     *
-     * @param servicePID PID of the service
-     */
-    public ByteArrayFileCache(String servicePID) {
-        // TODO track and limit folder size
-        // TODO support user specific folder
-        cacheFolder = new File(new File(OpenHAB.getUserDataFolder(), CACHE_FOLDER_NAME), servicePID);
-        if (!cacheFolder.exists()) {
-            logger.debug("Creating cache folder '{}'", cacheFolder.getAbsolutePath());
-            cacheFolder.mkdirs();
-        }
-        logger.debug("Using cache folder '{}'", cacheFolder.getAbsolutePath());
-    }
-
-    /**
-     * Creates a new {@link ByteArrayFileCache} instance for a service. Creates a <code>cache</code> folder under
-     * <code>$userdata/cache/$servicePID/</code>.
-     *
-     * @param servicePID PID of the service
-     * @param int the days for how long the files stay in the cache valid. Must be positive. 0 to
-     *            disables this functionality.
-     */
-    public ByteArrayFileCache(String servicePID, int expiry) {
-        this(servicePID);
-        if (expiry < 0) {
-            throw new IllegalArgumentException("Cache expiration time must be greater than or equal to 0");
-        }
-        this.expiry = expiry;
-    }
-
-    /**
-     * Adds a file to the cache. If the cache previously contained a file for the key, the old file is replaced by the
-     * new content.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     */
-    public void put(String key, byte[] content) {
-        writeFile(getUniqueFile(key), content);
-    }
-
-    /**
-     * Adds a file to the cache.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     */
-    public void putIfAbsent(String key, byte[] content) {
-        File fileInCache = getUniqueFile(key);
-        if (fileInCache.exists()) {
-            logger.debug("File '{}' present in cache", fileInCache.getName());
-            // update time of last use
-            fileInCache.setLastModified(System.currentTimeMillis());
-        } else {
-            writeFile(fileInCache, content);
-        }
-    }
-
-    /**
-     * Adds a file to the cache and returns the content of the file.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     * @return the content of the file associated with the given key
-     */
-    public byte[] putIfAbsentAndGet(String key, byte[] content) {
-        putIfAbsent(key, content);
-
-        return content;
-    }
-
-    /**
-     * Writes the given content to the given {@link File}.
-     *
-     * @param fileInCache the {@link File}
-     * @param content the content to be written
-     */
-    private void writeFile(File fileInCache, byte[] content) {
-        logger.debug("Caching file '{}'", fileInCache.getName());
-        try {
-            Files.write(fileInCache.toPath(), content);
-        } catch (IOException e) {
-            logger.warn("Could not write file '{}' to cache", fileInCache.getName(), e);
-        }
-    }
-
-    /**
-     * Checks if the key is present in the cache.
-     *
-     * @param key the key whose presence in the cache is to be tested
-     * @return true if the cache contains a file for the specified key
-     */
-    public boolean containsKey(String key) {
-        return getUniqueFile(key).exists();
-    }
-
-    /**
-     * Removes the file associated with the given key from the cache.
-     *
-     * @param key the key whose associated file is to be removed
-     */
-    public void remove(String key) {
-        deleteFile(getUniqueFile(key));
-    }
-
-    /**
-     * Deletes the given {@link File}.
-     *
-     * @param fileInCache the {@link File}
-     */
-    private void deleteFile(File fileInCache) {
-        if (fileInCache.exists()) {
-            logger.debug("Deleting file '{}' from cache", fileInCache.getName());
-            fileInCache.delete();
-        } else {
-            logger.debug("File '{}' not found in cache", fileInCache.getName());
-        }
-    }
-
-    /**
-     * Removes all files from the cache.
-     */
-    public void clear() {
-        File[] filesInCache = cacheFolder.listFiles();
-        if (filesInCache != null && filesInCache.length > 0) {
-            logger.debug("Deleting all files from cache");
-            Arrays.stream(filesInCache).forEach(File::delete);
-        }
-    }
-
-    /**
-     * Removes expired files from the cache.
-     */
-    public void clearExpired() {
-        // exit if expiry is set to 0 (disabled)
-        if (expiry <= 0) {
-            return;
-        }
-        File[] filesInCache = cacheFolder.listFiles();
-        if (filesInCache != null && filesInCache.length > 0) {
-            logger.debug("Deleting expired files from cache");
-            Arrays.stream(filesInCache).filter(file -> isExpired(file)).forEach(File::delete);
-        }
-    }
-
-    /**
-     * Checks if the given {@link File} is expired.
-     *
-     * @param fileInCache the {@link File}
-     * @return <code>true</code> if the file is expired, <code>false</code> otherwise
-     */
-    private boolean isExpired(File fileInCache) {
-        // exit if expiry is set to 0 (disabled)
-        if (expiry <= 0) {
-            return false;
-        }
-        return expiry * ONE_DAY_IN_MILLIS < System.currentTimeMillis() - fileInCache.lastModified();
-    }
-
-    /**
-     * Returns the content of the file associated with the given key, if it is present.
-     *
-     * @param key the key whose associated file is to be returned
-     * @return the content of the file associated with the given key
-     */
-    public byte[] get(String key) {
-        return readFile(getUniqueFile(key));
-    }
-
-    /**
-     * Reads the content from the given {@link File}, if it is present.
-     *
-     * @param fileInCache the {@link File}
-     * @return the content of the file
-     */
-    private byte[] readFile(File fileInCache) {
-        if (fileInCache.exists()) {
-            logger.debug("Reading file '{}' from cache", fileInCache.getName());
-            // update time of last use
-            fileInCache.setLastModified(System.currentTimeMillis());
-            try {
-                return Files.readAllBytes(fileInCache.toPath());
-            } catch (IOException e) {
-                logger.warn("Could not read file '{}' from cache", fileInCache.getName(), e);
-            }
-        } else {
-            logger.debug("File '{}' not found in cache", fileInCache.getName());
-        }
-        return new byte[0];
-    }
-
-    /**
-     * Creates a unique {@link File} from the key with which the file is to be associated.
-     *
-     * @param key the key with which the file is to be associated
-     * @return unique file for the file associated with the given key
-     */
-    File getUniqueFile(String key) {
-        String uniqueFileName = getUniqueFileName(key);
-        if (FILES_IN_CACHE.containsKey(uniqueFileName)) {
-            return FILES_IN_CACHE.get(uniqueFileName);
-        } else {
-            String fileExtension = getFileExtension(key);
-            File fileInCache = new File(cacheFolder,
-                    uniqueFileName + (fileExtension == null ? "" : EXTENSION_SEPARATOR + fileExtension));
-            FILES_IN_CACHE.put(uniqueFileName, fileInCache);
-            return fileInCache;
-        }
-    }
-
-    /**
-     * Gets the extension of a file name.
-     *
-     * @param fileName the file name to retrieve the extension of
-     * @return the extension of the file or null if none exists
-     */
-    @Nullable
-    String getFileExtension(String fileName) {
-        int extensionPos = fileName.lastIndexOf(EXTENSION_SEPARATOR);
-        int lastSeparatorPos = Math.max(fileName.lastIndexOf(UNIX_SEPARATOR), fileName.lastIndexOf(WINDOWS_SEPARATOR));
-        return lastSeparatorPos > extensionPos ? null : fileName.substring(extensionPos + 1);
-    }
-
-    /**
-     * Creates a unique file name from the key with which the file is to be associated.
-     *
-     * @param key the key with which the file is to be associated
-     * @return unique file name for the file associated with the given key
-     */
-    String getUniqueFileName(String key) {
-        try {
-            MessageDigest md = MessageDigest.getInstance(MD5_ALGORITHM);
-            byte[] bytesOfKey = key.getBytes(StandardCharsets.UTF_8);
-            byte[] md5Hash = md.digest(bytesOfKey);
-            BigInteger bigInt = new BigInteger(1, md5Hash);
-            String fileNameHash = bigInt.toString(16);
-            // Now we need to zero pad it if you actually want the full 32 chars
-            while (fileNameHash.length() < 32) {
-                fileNameHash = "0" + fileNameHash;
-            }
-            return fileNameHash;
-        } catch (NoSuchAlgorithmException ex) {
-            // should not happen
-            logger.error("Could not create MD5 hash for key '{}'", key, ex);
-            return key;
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.darksky/src/test/java/org/openhab/binding/darksky/internal/utils/ByteArrayFileCacheTest.java b/bundles/org.openhab.binding.darksky/src/test/java/org/openhab/binding/darksky/internal/utils/ByteArrayFileCacheTest.java
deleted file mode 100644 (file)
index a0d8bd4..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * Copyright (c) 2010-2020 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.darksky.internal.utils;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.openhab.core.OpenHAB;
-
-/**
- * Test class for the {@link ByteArrayFileCache} class.
- *
- * @author Christoph Weitkamp - Initial contribution
- */
-public class ByteArrayFileCacheTest {
-
-    private static final String SERVICE_PID = "org.openhab.binding.darksky";
-
-    private static final File USERDATA_FOLDER = new File(OpenHAB.getUserDataFolder());
-    private static final File CACHE_FOLDER = new File(USERDATA_FOLDER, ByteArrayFileCache.CACHE_FOLDER_NAME);
-    private static final File SERVICE_CACHE_FOLDER = new File(CACHE_FOLDER, SERVICE_PID);
-
-    private static final String MP3_FILE_NAME = SERVICE_CACHE_FOLDER.getAbsolutePath() + "doorbell.mp3";
-    private static final String TXT_FILE_NAME = SERVICE_CACHE_FOLDER.getAbsolutePath() + "doorbell.txt";
-
-    private static final byte[] EMPTY_BUFFER = new byte[0];
-
-    private ByteArrayFileCache subject;
-
-    @BeforeEach
-    public void setUp() {
-        subject = new ByteArrayFileCache(SERVICE_PID);
-    }
-
-    @AfterEach
-    public void tearDown() {
-        // delete all files
-        subject.clear();
-    }
-
-    @AfterAll
-    public static void cleanUp() {
-        // delete all folders
-        SERVICE_CACHE_FOLDER.delete();
-        CACHE_FOLDER.delete();
-        USERDATA_FOLDER.delete();
-    }
-
-    @Test
-    public void testGetFileExtension() {
-        assertThat(subject.getFileExtension("/var/log/openhab2/"), is(nullValue()));
-        assertThat(subject.getFileExtension("/var/log/foo.bar/"), is(nullValue()));
-        assertThat(subject.getFileExtension("doorbell.mp3"), is(equalTo("mp3")));
-        assertThat(subject.getFileExtension("/tmp/doorbell.mp3"), is(equalTo("mp3")));
-        assertThat(subject.getFileExtension(MP3_FILE_NAME), is(equalTo("mp3")));
-        assertThat(subject.getFileExtension(TXT_FILE_NAME), is(equalTo("txt")));
-        assertThat(subject.getFileExtension("/var/log/openhab2/.."), is(""));
-        assertThat(subject.getFileExtension(".hidden"), is(equalTo("hidden")));
-        assertThat(subject.getFileExtension("C:\\Program Files (x86)\\java\\bin\\javaw.exe"), is(equalTo("exe")));
-        assertThat(subject.getFileExtension("https://www.youtube.com/watch?v=qYrpPrLY868"), is(nullValue()));
-    }
-
-    @Test
-    public void testGetUniqueFileName() {
-        String mp3UniqueFileName = subject.getUniqueFileName(MP3_FILE_NAME);
-        assertThat(mp3UniqueFileName, is(equalTo(subject.getUniqueFileName(MP3_FILE_NAME))));
-
-        String txtUniqueFileName = subject.getUniqueFileName(TXT_FILE_NAME);
-        assertThat(txtUniqueFileName, is(equalTo(subject.getUniqueFileName(TXT_FILE_NAME))));
-
-        assertThat(mp3UniqueFileName, is(not(equalTo(txtUniqueFileName))));
-    }
-
-    @Test
-    public void testGet() {
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(EMPTY_BUFFER)));
-    }
-
-    @Test
-    public void testPut() throws IOException {
-        byte[] buffer = readFile();
-        subject.put(MP3_FILE_NAME, buffer);
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(buffer)));
-    }
-
-    @Test
-    public void testPutIfAbsent() throws IOException {
-        byte[] buffer = readFile();
-        subject.putIfAbsent(MP3_FILE_NAME, buffer);
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(buffer)));
-    }
-
-    @Test
-    public void testPutIfAbsentAndGet() throws IOException {
-        byte[] buffer = readFile();
-
-        assertThat(subject.putIfAbsentAndGet(MP3_FILE_NAME, buffer), is(equalTo(buffer)));
-    }
-
-    @Test
-    public void testContainsKey() throws IOException {
-        assertThat(subject.containsKey(MP3_FILE_NAME), is(false));
-
-        subject.put(MP3_FILE_NAME, readFile());
-
-        assertThat(subject.containsKey(MP3_FILE_NAME), is(true));
-    }
-
-    @Test
-    public void testRemove() throws IOException {
-        subject.put(MP3_FILE_NAME, readFile());
-        subject.remove(MP3_FILE_NAME);
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(EMPTY_BUFFER)));
-    }
-
-    @Test
-    public void testClear() throws IOException {
-        subject.put(MP3_FILE_NAME, readFile());
-        subject.clear();
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(EMPTY_BUFFER)));
-    }
-
-    @Test
-    public void clearExpiredClearsNothing() throws IOException {
-        byte[] buffer = readFile();
-        subject.put(MP3_FILE_NAME, buffer);
-        subject.clearExpired();
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(buffer)));
-    }
-
-    @Test
-    public void clearExpired() throws IOException {
-        subject = new ByteArrayFileCache(SERVICE_PID, 1);
-
-        subject.put(MP3_FILE_NAME, readFile());
-
-        // manipulate time of last use
-        File fileInCache = subject.getUniqueFile(MP3_FILE_NAME);
-        fileInCache.setLastModified(System.currentTimeMillis() - 2 * ByteArrayFileCache.ONE_DAY_IN_MILLIS);
-
-        subject.clearExpired();
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(EMPTY_BUFFER)));
-    }
-
-    private byte[] readFile() throws IOException {
-        byte[] buffer;
-        try (InputStream is = ByteArrayFileCacheTest.class.getResourceAsStream("/sounds/doorbell.mp3")) {
-            buffer = new byte[is.available()];
-            is.read(buffer);
-        }
-        return buffer;
-    }
-}
diff --git a/bundles/org.openhab.binding.darksky/src/test/resources/sounds/doorbell.mp3 b/bundles/org.openhab.binding.darksky/src/test/resources/sounds/doorbell.mp3
deleted file mode 100644 (file)
index 7a8a5a3..0000000
Binary files a/bundles/org.openhab.binding.darksky/src/test/resources/sounds/doorbell.mp3 and /dev/null differ
index bd51cb9137f6acee6ab44565e3c9b967890229cd..a1afeb163b3635bffb1fbc9471bb8be5725be2e9 100644 (file)
@@ -40,7 +40,7 @@ import org.openhab.binding.kodi.internal.model.KodiSubtitle;
 import org.openhab.binding.kodi.internal.model.KodiSystemProperties;
 import org.openhab.binding.kodi.internal.model.KodiUniqueID;
 import org.openhab.binding.kodi.internal.model.KodiVideoStream;
-import org.openhab.binding.kodi.internal.utils.ByteArrayFileCache;
+import org.openhab.core.cache.ByteArrayFileCache;
 import org.openhab.core.cache.ExpiringCacheMap;
 import org.openhab.core.io.net.http.HttpUtil;
 import org.openhab.core.library.types.RawType;
@@ -891,10 +891,14 @@ public class KodiConnection implements KodiClientSocketEventListener {
 
     private @Nullable RawType downloadImageFromCache(String url) {
         if (IMAGE_CACHE.containsKey(url)) {
-            byte[] bytes = IMAGE_CACHE.get(url);
-            String contentType = HttpUtil.guessContentTypeFromData(bytes);
-            return new RawType(bytes,
-                    contentType == null || contentType.isEmpty() ? RawType.DEFAULT_MIME_TYPE : contentType);
+            try {
+                byte[] bytes = IMAGE_CACHE.get(url);
+                String contentType = HttpUtil.guessContentTypeFromData(bytes);
+                return new RawType(bytes,
+                        contentType == null || contentType.isEmpty() ? RawType.DEFAULT_MIME_TYPE : contentType);
+            } catch (IOException e) {
+                logger.trace("Failed to download the content of URL '{}'", url, e);
+            }
         } else {
             RawType image = downloadImage(url);
             if (image != null) {
diff --git a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/utils/ByteArrayFileCache.java b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/utils/ByteArrayFileCache.java
deleted file mode 100644 (file)
index 9eced3e..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/**
- * Copyright (c) 2010-2020 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.kodi.internal.utils;
-
-import java.io.File;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.OpenHAB;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This is a simple file based cache implementation.
- *
- * @author Christoph Weitkamp - Initial contribution
- */
-@NonNullByDefault
-public class ByteArrayFileCache {
-
-    private final Logger logger = LoggerFactory.getLogger(ByteArrayFileCache.class);
-
-    private static final String MD5_ALGORITHM = "MD5";
-
-    static final String CACHE_FOLDER_NAME = "cache";
-    private static final char EXTENSION_SEPARATOR = '.';
-    private static final char UNIX_SEPARATOR = '/';
-    private static final char WINDOWS_SEPARATOR = '\\';
-
-    private final File cacheFolder;
-
-    static final long ONE_DAY_IN_MILLIS = TimeUnit.DAYS.toMillis(1);
-    private int expiry = 0;
-
-    private static final Map<String, File> FILES_IN_CACHE = new ConcurrentHashMap<>();
-
-    /**
-     * Creates a new {@link ByteArrayFileCache} instance for a service. Creates a <code>cache</code> folder under
-     * <code>$userdata/cache/$servicePID</code>.
-     *
-     * @param servicePID PID of the service
-     */
-    public ByteArrayFileCache(String servicePID) {
-        // TODO track and limit folder size
-        // TODO support user specific folder
-        cacheFolder = new File(new File(OpenHAB.getUserDataFolder(), CACHE_FOLDER_NAME), servicePID);
-        if (!cacheFolder.exists()) {
-            logger.debug("Creating cache folder '{}'", cacheFolder.getAbsolutePath());
-            cacheFolder.mkdirs();
-        }
-        logger.debug("Using cache folder '{}'", cacheFolder.getAbsolutePath());
-    }
-
-    /**
-     * Creates a new {@link ByteArrayFileCache} instance for a service. Creates a <code>cache</code> folder under
-     * <code>$userdata/cache/$servicePID/</code>.
-     *
-     * @param servicePID PID of the service
-     * @param int the days for how long the files stay in the cache valid. Must be positive. 0 to
-     *            disables this functionality.
-     */
-    public ByteArrayFileCache(String servicePID, int expiry) {
-        this(servicePID);
-        if (expiry < 0) {
-            throw new IllegalArgumentException("Cache expiration time must be greater than or equal to 0");
-        }
-        this.expiry = expiry;
-    }
-
-    /**
-     * Adds a file to the cache. If the cache previously contained a file for the key, the old file is replaced by the
-     * new content.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     */
-    public void put(String key, byte[] content) {
-        writeFile(getUniqueFile(key), content);
-    }
-
-    /**
-     * Adds a file to the cache.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     */
-    public void putIfAbsent(String key, byte[] content) {
-        File fileInCache = getUniqueFile(key);
-        if (fileInCache.exists()) {
-            logger.debug("File '{}' present in cache", fileInCache.getName());
-            // update time of last use
-            fileInCache.setLastModified(System.currentTimeMillis());
-        } else {
-            writeFile(fileInCache, content);
-        }
-    }
-
-    /**
-     * Adds a file to the cache and returns the content of the file.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     * @return the content of the file associated with the given key
-     */
-    public byte[] putIfAbsentAndGet(String key, byte[] content) {
-        putIfAbsent(key, content);
-
-        return content;
-    }
-
-    /**
-     * Writes the given content to the given {@link File}.
-     *
-     * @param fileInCache the {@link File}
-     * @param content the content to be written
-     */
-    private void writeFile(File fileInCache, byte[] content) {
-        logger.debug("Caching file '{}'", fileInCache.getName());
-        try {
-            Files.write(fileInCache.toPath(), content);
-        } catch (IOException e) {
-            logger.warn("Could not write file '{}' to cache", fileInCache.getName(), e);
-        }
-    }
-
-    /**
-     * Checks if the key is present in the cache.
-     *
-     * @param key the key whose presence in the cache is to be tested
-     * @return true if the cache contains a file for the specified key
-     */
-    public boolean containsKey(String key) {
-        return getUniqueFile(key).exists();
-    }
-
-    /**
-     * Removes the file associated with the given key from the cache.
-     *
-     * @param key the key whose associated file is to be removed
-     */
-    public void remove(String key) {
-        deleteFile(getUniqueFile(key));
-    }
-
-    /**
-     * Deletes the given {@link File}.
-     *
-     * @param fileInCache the {@link File}
-     */
-    private void deleteFile(File fileInCache) {
-        if (fileInCache.exists()) {
-            logger.debug("Deleting file '{}' from cache", fileInCache.getName());
-            fileInCache.delete();
-        } else {
-            logger.debug("File '{}' not found in cache", fileInCache.getName());
-        }
-    }
-
-    /**
-     * Removes all files from the cache.
-     */
-    public void clear() {
-        File[] filesInCache = cacheFolder.listFiles();
-        if (filesInCache != null && filesInCache.length > 0) {
-            logger.debug("Deleting all files from cache");
-            Arrays.stream(filesInCache).forEach(File::delete);
-        }
-    }
-
-    /**
-     * Removes expired files from the cache.
-     */
-    public void clearExpired() {
-        // exit if expiry is set to 0 (disabled)
-        if (expiry <= 0) {
-            return;
-        }
-        File[] filesInCache = cacheFolder.listFiles();
-        if (filesInCache != null && filesInCache.length > 0) {
-            logger.debug("Deleting expired files from cache");
-            Arrays.stream(filesInCache).filter(file -> isExpired(file)).forEach(File::delete);
-        }
-    }
-
-    /**
-     * Checks if the given {@link File} is expired.
-     *
-     * @param fileInCache the {@link File}
-     * @return <code>true</code> if the file is expired, <code>false</code> otherwise
-     */
-    private boolean isExpired(File fileInCache) {
-        // exit if expiry is set to 0 (disabled)
-        if (expiry <= 0) {
-            return false;
-        }
-        return expiry * ONE_DAY_IN_MILLIS < System.currentTimeMillis() - fileInCache.lastModified();
-    }
-
-    /**
-     * Returns the content of the file associated with the given key, if it is present.
-     *
-     * @param key the key whose associated file is to be returned
-     * @return the content of the file associated with the given key
-     */
-    public byte[] get(String key) {
-        return readFile(getUniqueFile(key));
-    }
-
-    /**
-     * Reads the content from the given {@link File}, if it is present.
-     *
-     * @param fileInCache the {@link File}
-     * @return the content of the file
-     */
-    private byte[] readFile(File fileInCache) {
-        if (fileInCache.exists()) {
-            logger.debug("Reading file '{}' from cache", fileInCache.getName());
-            // update time of last use
-            fileInCache.setLastModified(System.currentTimeMillis());
-            try {
-                return Files.readAllBytes(fileInCache.toPath());
-            } catch (IOException e) {
-                logger.warn("Could not read file '{}' from cache", fileInCache.getName(), e);
-            }
-        } else {
-            logger.debug("File '{}' not found in cache", fileInCache.getName());
-        }
-        return new byte[0];
-    }
-
-    /**
-     * Creates a unique {@link File} from the key with which the file is to be associated.
-     *
-     * @param key the key with which the file is to be associated
-     * @return unique file for the file associated with the given key
-     */
-    File getUniqueFile(String key) {
-        String uniqueFileName = getUniqueFileName(key);
-        if (FILES_IN_CACHE.containsKey(uniqueFileName)) {
-            return FILES_IN_CACHE.get(uniqueFileName);
-        } else {
-            String fileExtension = getFileExtension(key);
-            File fileInCache = new File(cacheFolder,
-                    uniqueFileName + (fileExtension == null ? "" : EXTENSION_SEPARATOR + fileExtension));
-            FILES_IN_CACHE.put(uniqueFileName, fileInCache);
-            return fileInCache;
-        }
-    }
-
-    /**
-     * Gets the extension of a file name.
-     *
-     * @param fileName the file name to retrieve the extension of
-     * @return the extension of the file or null if none exists
-     */
-    @Nullable
-    String getFileExtension(String fileName) {
-        int extensionPos = fileName.lastIndexOf(EXTENSION_SEPARATOR);
-        int lastSeparatorPos = Math.max(fileName.lastIndexOf(UNIX_SEPARATOR), fileName.lastIndexOf(WINDOWS_SEPARATOR));
-        return lastSeparatorPos > extensionPos ? null : fileName.substring(extensionPos + 1).replaceFirst("\\?.*$", "");
-    }
-
-    /**
-     * Creates a unique file name from the key with which the file is to be associated.
-     *
-     * @param key the key with which the file is to be associated
-     * @return unique file name for the file associated with the given key
-     */
-    String getUniqueFileName(String key) {
-        try {
-            MessageDigest md = MessageDigest.getInstance(MD5_ALGORITHM);
-            byte[] bytesOfKey = key.getBytes(StandardCharsets.UTF_8);
-            byte[] md5Hash = md.digest(bytesOfKey);
-            BigInteger bigInt = new BigInteger(1, md5Hash);
-            String fileNameHash = bigInt.toString(16);
-            // We need to zero pad it if you actually want the full 32 chars
-            while (fileNameHash.length() < 32) {
-                fileNameHash = "0" + fileNameHash;
-            }
-            return fileNameHash;
-        } catch (NoSuchAlgorithmException ex) {
-            // should not happen
-            logger.error("Could not create MD5 hash for key '{}'", key, ex);
-            return key;
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.kodi/src/test/java/org/openhab/binding/kodi/internal/utils/ByteArrayFileCacheTest.java b/bundles/org.openhab.binding.kodi/src/test/java/org/openhab/binding/kodi/internal/utils/ByteArrayFileCacheTest.java
deleted file mode 100644 (file)
index cee8c42..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * Copyright (c) 2010-2020 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.kodi.internal.utils;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.openhab.core.OpenHAB;
-
-/**
- * Test class for the {@link ByteArrayFileCache} class.
- *
- * @author Christoph Weitkamp - Initial contribution
- */
-public class ByteArrayFileCacheTest {
-
-    private static final String SERVICE_PID = "org.openhab.binding.kodi";
-
-    private static final File USERDATA_FOLDER = new File(OpenHAB.getUserDataFolder());
-    private static final File CACHE_FOLDER = new File(USERDATA_FOLDER, ByteArrayFileCache.CACHE_FOLDER_NAME);
-    private static final File SERVICE_CACHE_FOLDER = new File(CACHE_FOLDER, SERVICE_PID);
-
-    private static final String MP3_FILE_NAME = SERVICE_CACHE_FOLDER.getAbsolutePath() + "doorbell.mp3";
-    private static final String TXT_FILE_NAME = SERVICE_CACHE_FOLDER.getAbsolutePath() + "doorbell.txt";
-
-    private static final byte[] EMPTY_BUFFER = new byte[0];
-
-    private ByteArrayFileCache subject;
-
-    @BeforeEach
-    public void setUp() {
-        subject = new ByteArrayFileCache(SERVICE_PID);
-    }
-
-    @AfterEach
-    public void tearDown() {
-        // delete all files
-        subject.clear();
-    }
-
-    @AfterAll
-    public static void cleanUp() {
-        // delete all folders
-        SERVICE_CACHE_FOLDER.delete();
-        CACHE_FOLDER.delete();
-        USERDATA_FOLDER.delete();
-    }
-
-    @Test
-    public void testGetFileExtension() {
-        assertThat(subject.getFileExtension("/var/log/openhab2/"), is(nullValue()));
-        assertThat(subject.getFileExtension("/var/log/foo.bar/"), is(nullValue()));
-        assertThat(subject.getFileExtension("doorbell.mp3"), is(equalTo("mp3")));
-        assertThat(subject.getFileExtension("/tmp/doorbell.mp3"), is(equalTo("mp3")));
-        assertThat(subject.getFileExtension(MP3_FILE_NAME), is(equalTo("mp3")));
-        assertThat(subject.getFileExtension(TXT_FILE_NAME), is(equalTo("txt")));
-        assertThat(subject.getFileExtension("/var/log/openhab2/.."), is(""));
-        assertThat(subject.getFileExtension(".hidden"), is(equalTo("hidden")));
-        assertThat(subject.getFileExtension("C:\\Program Files (x86)\\java\\bin\\javaw.exe"), is(equalTo("exe")));
-        assertThat(subject.getFileExtension("https://www.youtube.com/watch?v=qYrpPrLY868"), is(nullValue()));
-        assertThat(subject.getFileExtension(
-                "a52fc16cca77ab2bf6abe51e463ce501.jpg?response-content-type=image%2Fjpeg&test=1"), is("jpg"));
-    }
-
-    @Test
-    public void testGetUniqueFileNameIsUnique() {
-        String mp3UniqueFileName = subject.getUniqueFileName(MP3_FILE_NAME);
-        assertThat(mp3UniqueFileName, is(equalTo(subject.getUniqueFileName(MP3_FILE_NAME))));
-
-        String txtUniqueFileName = subject.getUniqueFileName(TXT_FILE_NAME);
-        assertThat(txtUniqueFileName, is(equalTo(subject.getUniqueFileName(TXT_FILE_NAME))));
-
-        assertThat(mp3UniqueFileName, is(not(equalTo(txtUniqueFileName))));
-    }
-
-    @Test
-    public void testGet() {
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(EMPTY_BUFFER)));
-    }
-
-    @Test
-    public void testPut() throws IOException {
-        byte[] buffer = readFile();
-        subject.put(MP3_FILE_NAME, buffer);
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(buffer)));
-    }
-
-    @Test
-    public void testPutIfAbsent() throws IOException {
-        byte[] buffer = readFile();
-        subject.putIfAbsent(MP3_FILE_NAME, buffer);
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(buffer)));
-    }
-
-    @Test
-    public void testPutIfAbsentAndGet() throws IOException {
-        byte[] buffer = readFile();
-
-        assertThat(subject.putIfAbsentAndGet(MP3_FILE_NAME, buffer), is(equalTo(buffer)));
-    }
-
-    @Test
-    public void testContainsKey() throws IOException {
-        assertThat(subject.containsKey(MP3_FILE_NAME), is(false));
-
-        subject.put(MP3_FILE_NAME, readFile());
-
-        assertThat(subject.containsKey(MP3_FILE_NAME), is(true));
-    }
-
-    @Test
-    public void testRemove() throws IOException {
-        subject.put(MP3_FILE_NAME, readFile());
-        subject.remove(MP3_FILE_NAME);
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(EMPTY_BUFFER)));
-    }
-
-    @Test
-    public void testClear() throws IOException {
-        subject.put(MP3_FILE_NAME, readFile());
-        subject.clear();
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(EMPTY_BUFFER)));
-    }
-
-    @Test
-    public void clearExpiredClearsNothing() throws IOException {
-        byte[] buffer = readFile();
-        subject.put(MP3_FILE_NAME, buffer);
-        subject.clearExpired();
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(buffer)));
-    }
-
-    @Test
-    public void clearExpired() throws IOException {
-        subject = new ByteArrayFileCache(SERVICE_PID, 1);
-
-        subject.put(MP3_FILE_NAME, readFile());
-
-        // manipulate time of last use
-        File fileInCache = subject.getUniqueFile(MP3_FILE_NAME);
-        fileInCache.setLastModified(System.currentTimeMillis() - 2 * ByteArrayFileCache.ONE_DAY_IN_MILLIS);
-
-        subject.clearExpired();
-
-        assertThat(subject.get(MP3_FILE_NAME), is(equalTo(EMPTY_BUFFER)));
-    }
-
-    private byte[] readFile() throws IOException {
-        byte[] buffer;
-        try (InputStream is = ByteArrayFileCacheTest.class.getResourceAsStream("/sounds/doorbell.mp3")) {
-            buffer = new byte[is.available()];
-            is.read(buffer);
-        }
-        return buffer;
-    }
-}
diff --git a/bundles/org.openhab.binding.kodi/src/test/resources/sounds/doorbell.mp3 b/bundles/org.openhab.binding.kodi/src/test/resources/sounds/doorbell.mp3
deleted file mode 100644 (file)
index 7a8a5a3..0000000
Binary files a/bundles/org.openhab.binding.kodi/src/test/resources/sounds/doorbell.mp3 and /dev/null differ
index d82fb0bd3e7714adc9a2c0974f6430c0835f6635..d2705e68a0f367b192a2c69fb240756e04190169 100644 (file)
@@ -16,6 +16,7 @@ import static java.util.stream.Collectors.joining;
 import static org.eclipse.jetty.http.HttpMethod.GET;
 import static org.eclipse.jetty.http.HttpStatus.*;
 
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
@@ -38,7 +39,7 @@ import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonHourlyF
 import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonUVIndexData;
 import org.openhab.binding.openweathermap.internal.dto.OpenWeatherMapJsonWeatherData;
 import org.openhab.binding.openweathermap.internal.handler.OpenWeatherMapAPIHandler;
-import org.openhab.binding.openweathermap.internal.utils.ByteArrayFileCache;
+import org.openhab.core.cache.ByteArrayFileCache;
 import org.openhab.core.cache.ExpiringCacheMap;
 import org.openhab.core.io.net.http.HttpUtil;
 import org.openhab.core.library.types.PointType;
@@ -224,7 +225,12 @@ public class OpenWeatherMapConnection {
 
     private static @Nullable RawType downloadWeatherIconFromCache(String url) {
         if (IMAGE_CACHE.containsKey(url)) {
-            return new RawType(IMAGE_CACHE.get(url), PNG_CONTENT_TYPE);
+            try {
+                return new RawType(IMAGE_CACHE.get(url), PNG_CONTENT_TYPE);
+            } catch (IOException e) {
+                LoggerFactory.getLogger(OpenWeatherMapConnection.class)
+                        .trace("Failed to download the content of URL '{}'", url, e);
+            }
         } else {
             RawType image = downloadWeatherIcon(url);
             if (image != null) {
diff --git a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/utils/ByteArrayFileCache.java b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/utils/ByteArrayFileCache.java
deleted file mode 100644 (file)
index e2edd6b..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/**
- * Copyright (c) 2010-2020 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.binding.openweathermap.internal.utils;
-
-import java.io.File;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.OpenHAB;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This is a simple file based cache implementation.
- *
- * @author Christoph Weitkamp - Initial contribution
- */
-@NonNullByDefault
-public class ByteArrayFileCache {
-
-    private final Logger logger = LoggerFactory.getLogger(ByteArrayFileCache.class);
-
-    private static final String CACHE_FOLDER_NAME = "cache";
-    public static final char EXTENSION_SEPARATOR = '.';
-
-    protected final File cacheFolder;
-
-    public ByteArrayFileCache(String servicePID) {
-        // TODO track and limit folder size
-        // TODO support user specific folder
-        cacheFolder = new File(new File(new File(OpenHAB.getUserDataFolder()), CACHE_FOLDER_NAME), servicePID);
-        if (!cacheFolder.exists()) {
-            logger.debug("Creating cache folder '{}'", cacheFolder.getAbsolutePath());
-            cacheFolder.mkdirs();
-        }
-        logger.debug("Using cache folder '{}'", cacheFolder.getAbsolutePath());
-    }
-
-    /**
-     * Adds a file to the cache. If the cache previously contained a file for the key, the old file is replaced by the
-     * new content.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     */
-    public void put(String key, byte[] content) {
-        writeFile(getUniqueFile(key), content);
-    }
-
-    /**
-     * Adds a file to the cache.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     */
-    public void putIfAbsent(String key, byte[] content) {
-        File fileInCache = getUniqueFile(key);
-        if (fileInCache.exists()) {
-            logger.debug("File '{}' present in cache", fileInCache.getName());
-        } else {
-            writeFile(fileInCache, content);
-        }
-    }
-
-    /**
-     * Adds a file to the cache and returns the content of the file.
-     *
-     * @param key the key with which the file is to be associated
-     * @param content the content for the file to be associated with the specified key
-     * @return the content of the file associated with the given key
-     */
-    public byte[] putIfAbsentAndGet(String key, byte[] content) {
-        putIfAbsent(key, content);
-
-        // return get(key);
-        return content;
-    }
-
-    /**
-     * Writes the given content to the given {@link File}.
-     *
-     * @param fileInCache the {@link File}
-     * @param content the content to be written
-     */
-    private void writeFile(File fileInCache, byte[] content) {
-        logger.debug("Caching file '{}'", fileInCache.getName());
-        try {
-            Files.write(fileInCache.toPath(), content);
-        } catch (IOException e) {
-            logger.warn("Could not write file '{}' to cache", fileInCache.getName(), e);
-        }
-    }
-
-    /**
-     * Checks if the key is present in the cache.
-     *
-     * @param key the key whose presence in the cache is to be tested
-     * @return true if the cache contains a file for the specified key
-     */
-    public boolean containsKey(String key) {
-        return getUniqueFile(key).exists();
-    }
-
-    /**
-     * Removes the file associated with the given key from the cache.
-     *
-     * @param key the key whose associated file is to be removed
-     */
-    public void remove(String key) {
-        deleteFile(getUniqueFile(key));
-    }
-
-    /**
-     * Deletes the given {@link File}.
-     *
-     * @param fileInCache the {@link File}
-     */
-    private void deleteFile(File fileInCache) {
-        if (fileInCache.exists()) {
-            logger.debug("Deleting file '{}' from cache", fileInCache.getName());
-            fileInCache.delete();
-        } else {
-            logger.debug("File '{}' not found in cache", fileInCache.getName());
-        }
-    }
-
-    /**
-     * Removes all files from the cache.
-     */
-    public void clear() {
-        File[] filesInCache = cacheFolder.listFiles();
-        if (filesInCache != null && filesInCache.length > 0) {
-            logger.debug("Deleting all files from cache");
-            Arrays.stream(filesInCache).forEach(File::delete);
-        }
-    }
-
-    /**
-     * Returns the content of the file associated with the given key, if it is present.
-     *
-     * @param key the key whose associated file is to be returned
-     * @return the content of the file associated with the given key
-     */
-    public byte[] get(String key) {
-        return readFile(getUniqueFile(key));
-    }
-
-    /**
-     * Reads the content from the given {@link File}, if it is present.
-     *
-     * @param fileInCache the {@link File}
-     * @return the content of the file
-     */
-    private byte[] readFile(File fileInCache) {
-        if (fileInCache.exists()) {
-            logger.debug("Reading file '{}' from cache", fileInCache.getName());
-            try {
-                return Files.readAllBytes(fileInCache.toPath());
-            } catch (IOException e) {
-                logger.warn("Could not read file '{}' from cache", fileInCache.getName(), e);
-            }
-        } else {
-            logger.debug("File '{}' not found in cache", fileInCache.getName());
-        }
-        return new byte[0];
-    }
-
-    /**
-     * Creates a unique {@link File} from the key with which the file is to be associated.
-     *
-     * @param key the key with which the file is to be associated
-     * @return unique file for the file associated with the given key
-     */
-    private File getUniqueFile(String key) {
-        // TODO: store / cache file internally for faster operations
-        String fileExtension = getFileExtension(key);
-        return new File(cacheFolder,
-                getUniqueFileName(key) + (fileExtension == null ? "" : EXTENSION_SEPARATOR + fileExtension));
-    }
-
-    /**
-     * Gets the extension of a file name.
-     *
-     * @param fileName the file name to retrieve the extension of
-     * @return the extension of the file or null if none exists
-     */
-    private @Nullable String getFileExtension(String fileName) {
-        int index = fileName.lastIndexOf(EXTENSION_SEPARATOR);
-        // exclude file names starting with a dot
-        if (index > 0) {
-            return fileName.substring(index + 1);
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Creates a unique file name from the key with which the file is to be associated.
-     *
-     * @param key the key with which the file is to be associated
-     * @return unique file name for the file associated with the given key
-     */
-    private String getUniqueFileName(String key) {
-        try {
-            byte[] bytesOfFileName = key.getBytes(StandardCharsets.UTF_8);
-            MessageDigest md = MessageDigest.getInstance("MD5");
-            byte[] md5Hash = md.digest(bytesOfFileName);
-            BigInteger bigInt = new BigInteger(1, md5Hash);
-            StringBuilder fileNameHash = new StringBuilder(bigInt.toString(16));
-            // Now we need to zero pad it if you actually want the full 32 chars
-            while (fileNameHash.length() < 32) {
-                fileNameHash.insert(0, "0");
-            }
-            return fileNameHash.toString();
-        } catch (NoSuchAlgorithmException ex) {
-            // should not happen
-            logger.error("Could not create MD5 hash for key '{}'", key, ex);
-            return key.toString();
-        }
-    }
-}