001/** 002 * Copyright (c) 2012, 2014, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016package org.javamoney.moneta.internal.loader; 017 018import java.io.*; 019import java.util.Map; 020import java.util.Objects; 021import java.util.concurrent.ConcurrentHashMap; 022import java.util.logging.Level; 023import java.util.logging.Logger; 024 025/** 026 * Default implementation of {@link ResourceCache}, using the local file system. 027 * 028 * @author Anatole Tresch 029 */ 030public class DefaultResourceCache implements ResourceCache { 031 /** 032 * The logger used. 033 */ 034 private static final Logger LOG = Logger.getLogger(DefaultResourceCache.class.getName()); 035 /** 036 * Suffix for files created. 037 */ 038 private static final String SUFFIX = ".dat"; 039 /** 040 * Local temp directory. 041 */ 042 private File localDir = new File(System.getProperty("temp.dir", ".resourceCache")); 043 /** 044 * Cached resources. 045 */ 046 private final Map<String, File> cachedResources = new ConcurrentHashMap<>(); 047 048 /** 049 * Constructor. 050 */ 051 public DefaultResourceCache() { 052 if (!localDir.exists()) { 053 if (!localDir.mkdirs()) { 054 LOG.severe("Error creating cache dir " + localDir + ", resource cache disabled!"); 055 localDir = null; 056 } else { 057 LOG.finest("Created cache dir " + localDir); 058 } 059 } else if (!localDir.isDirectory()) { 060 LOG.severe("Error initializing cache dir " + localDir + ", not a directory, resource cache disabled!"); 061 localDir = null; 062 } else if (!localDir.canWrite()) { 063 LOG.severe("Error initializing cache dir " + localDir + ", not writable, resource cache disabled!"); 064 localDir = null; 065 } 066 if (Objects.nonNull(localDir)) { 067 File[] files = localDir.listFiles(); 068 if (files != null) { 069 for (File file : files) { 070 if (file.isFile()) { 071 String resourceId = file.getName().substring(0, file.getName().length() - 4); 072 cachedResources.put(resourceId, file); 073 } 074 } 075 } 076 } 077 } 078 079 /* 080 * (non-Javadoc) 081 * 082 * @see 083 * org.javamoney.moneta.loader.format.ResourceCache#write(java.lang.String 084 * , byte[]) 085 */ 086 @Override 087 public void write(String resourceId, byte[] data) { 088 try { 089 File f = this.cachedResources.get(resourceId); 090 if (Objects.isNull(f)) { 091 f = new File(localDir, resourceId + SUFFIX); 092 writeFile(f, data); 093 this.cachedResources.put(resourceId, f); 094 } else { 095 writeFile(f, data); 096 } 097 } catch (Exception e) { 098 LOG.log(Level.WARNING, "Caching of resource failed: " + resourceId, e); 099 } 100 } 101 102 /** 103 * Writes a file with the given data, 104 * 105 * @param f the file 106 * @param data the data 107 * @throws IOException if writing failed. 108 */ 109 private void writeFile(File f, byte[] data) throws IOException { 110 BufferedOutputStream bos = null; 111 try { 112 bos = new BufferedOutputStream(new FileOutputStream(f)); 113 bos.write(data); 114 bos.flush(); 115 } finally { 116 try { 117 if (Objects.nonNull(bos)) { 118 bos.close(); 119 } 120 } catch (Exception e2) { 121 LOG.log(Level.SEVERE, "Error closing output stream for " + f, e2); 122 } 123 } 124 125 } 126 127 /* 128 * (non-Javadoc) 129 * 130 * @see 131 * org.javamoney.moneta.loader.format.ResourceCache#isCached(java.lang 132 * .String) 133 */ 134 @Override 135 public boolean isCached(String resourceId) { 136 return this.cachedResources.containsKey(resourceId); 137 } 138 139 /* 140 * (non-Javadoc) 141 * 142 * @see 143 * org.javamoney.moneta.loader.format.ResourceCache#read(java.lang.String) 144 */ 145 @Override 146 public byte[] read(String resourceId) { 147 File f = this.cachedResources.get(resourceId); 148 if (Objects.isNull(f)) { 149 return null; 150 } 151 return readFile(f); 152 } 153 154 @Override 155 public void clear(String resourceId) { 156 File f = this.cachedResources.get(resourceId); 157 if (f != null) { 158 if (f.exists()) { 159 if (!f.delete()) { 160 LOG.warning("Failed to delete caching file: " + f.getAbsolutePath()); 161 } 162 } 163 this.cachedResources.remove(resourceId); 164 } 165 } 166 167 /** 168 * Read a file. 169 * 170 * @param f the file 171 * @return the bytes read. 172 */ 173 private byte[] readFile(File f) { 174 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 175 BufferedInputStream is = null; 176 try { 177 is = new BufferedInputStream(new FileInputStream(f)); 178 byte[] input = new byte[1024]; 179 int read = 1; 180 while (read > 0) { 181 read = is.read(input); 182 if (read > 0) { 183 bos.write(input, 0, read); 184 } 185 } 186 return bos.toByteArray(); 187 } catch (Exception e) { 188 LOG.log(Level.SEVERE, "Error reading cached resource from " + f, e); 189 return null; 190 } finally { 191 try { 192 if (Objects.nonNull(is)) { 193 is.close(); 194 } 195 } catch (Exception e2) { 196 LOG.log(Level.SEVERE, "Error closing input stream from " + f, e2); 197 } 198 } 199/* 200URI fileUri = this.cachedResource; 201 if(fileUri == null){ 202 String userHome = System.getProperty("user.home"); 203 File file = new File(userHome + "/.cache", resourceId); 204 if(file.exists()){ 205 fileUri = file.toURI(); 206 } 207 } 208 if(fileUri != null){ 209 File file = new File(fileUri); 210 try( 211 FileInputStream fis = new FileInputStream(file); 212 BufferedInputStream bis = new BufferedInputStream(fis); 213 ObjectInputStream ois = new ObjectInputStream(bis) 214 ){ 215 long loadTS = ois.readLong(); 216 byte[] data = (byte[]) ois.readObject(); 217 this.lastLoaded = loadTS; 218 setData(data); 219 return true; 220 } 221 catch(Exception e){ 222 LOG.log(Level.WARNING, "Failed to read data from cache: " + fileUri, e); 223 } 224 } 225 return false; 226 */ 227 } 228 229 @Override 230 public String toString() { 231 return "DefaultResourceCache [localDir=" + localDir + ", cachedResources=" + cachedResources + ']'; 232 } 233 234}