/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.helpers;
import com.jpexs.decompiler.flash.helpers.Freed;
import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
/**
*
* @author JPEXS
* @param <K>
* @param <V>
*/
public class Cache<K, V> implements Freed {
private Map<K, V> cache;
private static final List<WeakReference<Cache>> instances = new ArrayList<>();
public static final int STORAGE_FILES = 1;
public static final int STORAGE_MEMORY = 2;
private final boolean weak;
private final boolean memoryOnly;
private final String name;
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
for (WeakReference<Cache> cw : instances) {
Cache c = cw.get();
if (c != null) {
c.clear();
c.free();
}
}
}
});
}
public static <K, V> Cache<K, V> getInstance(boolean weak, boolean memoryOnly, String name) {
Cache<K, V> instance = new Cache<>(weak, memoryOnly, name);
instances.add(new WeakReference<>(instance));
return instance;
}
private static int storageType = STORAGE_FILES;
public static void clearAll() {
for (WeakReference<Cache> cw : instances) {
Cache c = cw.get();
if (c != null) {
c.clear();
c.initCache();
}
}
}
public static void setStorageType(int storageType) {
if (storageType == Cache.storageType) {
return;
}
switch (storageType) {
case STORAGE_FILES:
case STORAGE_MEMORY:
break;
default:
throw new IllegalArgumentException("storageType must be one of STORAGE_FILES or STORAGE_MEMORY");
}
if (storageType != Cache.storageType) {
clearAll();
}
Cache.storageType = storageType;
}
public static int getStorageType() {
return storageType;
}
private void initCache() {
int thisStorageType = storageType;
if (memoryOnly) {
thisStorageType = STORAGE_MEMORY;
}
Map<K, V> newCache = null;
if (thisStorageType == STORAGE_FILES) {
try {
newCache = new FileHashMap<>(File.createTempFile("ffdec_cache_" + name + "_", ".tmp"));
} catch (IOException ex) {
thisStorageType = STORAGE_MEMORY;
}
}
if (thisStorageType == STORAGE_MEMORY) {
if (weak) {
newCache = new WeakHashMap<>();
} else {
newCache = new HashMap<>();
}
}
if (this.cache instanceof Freed) {
((Freed) this.cache).free();
}
this.cache = newCache;
}
private Cache(boolean weak, boolean memoryOnly, String name) {
this.weak = weak;
this.name = name;
this.memoryOnly = memoryOnly;
initCache();
}
public synchronized boolean contains(K key) {
return cache.containsKey(key);
}
public synchronized void clear() {
cache.clear();
}
public synchronized void remove(K key) {
if (cache.containsKey(key)) {
cache.remove(key);
}
}
public synchronized V get(K key) {
return cache.get(key);
}
public synchronized void put(K key, V value) {
cache.put(key, value);
}
@Override
public boolean isFreeing() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void free() {
if (cache instanceof Freed) {
((Freed) cache).free();
}
}
}