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.loader.internal; 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 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.internal.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 } 098 catch(Exception e){ 099 LOG.log(Level.WARNING, "Caching of resource failed: " + resourceId, e); 100 } 101 } 102 103 /** 104 * Writees a file with the given data, 105 * 106 * @param f the file 107 * @param data the data 108 * @throws IOException if writing failed. 109 */ 110 private void writeFile(File f, byte[] data) throws IOException{ 111 BufferedOutputStream bos = null; 112 try{ 113 bos = new BufferedOutputStream(new FileOutputStream(f)); 114 bos.write(data); 115 bos.flush(); 116 } 117 finally{ 118 try{ 119 if(Objects.nonNull(bos)){ 120 bos.close(); 121 } 122 } 123 catch(Exception e2){ 124 LOG.log(Level.SEVERE, "Error closing output stream for " + f, e2); 125 } 126 } 127 128 } 129 130 /* 131 * (non-Javadoc) 132 * 133 * @see 134 * org.javamoney.moneta.loader.internal.ResourceCache#isCached(java.lang 135 * .String) 136 */ 137 @Override 138 public boolean isCached(String resourceId){ 139 return this.cachedResources.containsKey(resourceId); 140 } 141 142 /* 143 * (non-Javadoc) 144 * 145 * @see 146 * org.javamoney.moneta.loader.internal.ResourceCache#read(java.lang.String) 147 */ 148 @Override 149 public byte[] read(String resourceId){ 150 File f = this.cachedResources.get(resourceId); 151 if(Objects.isNull(f)){ 152 return null; 153 } 154 return readFile(f); 155 } 156 157 @Override 158 public void clear(String resourceId){ 159 File f = this.cachedResources.get(resourceId); 160 if(f != null){ 161 if(f.exists()){ 162 if(!f.delete()){ 163 LOG.warning("Failed to delete caching file: " + f.getAbsolutePath()); 164 } 165 } 166 this.cachedResources.remove(resourceId); 167 } 168 } 169 170 /** 171 * Read a file. 172 * 173 * @param f the file 174 * @return the bytes read. 175 */ 176 private byte[] readFile(File f){ 177 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 178 BufferedInputStream is = null; 179 try{ 180 is = new BufferedInputStream(new FileInputStream(f)); 181 byte[] input = new byte[1024]; 182 int read = 1; 183 while(read > 0){ 184 read = is.read(input); 185 if(read > 0){ 186 bos.write(input, 0, read); 187 } 188 } 189 return bos.toByteArray(); 190 } 191 catch(Exception e){ 192 LOG.log(Level.SEVERE, "Error reading cached resource from " + f, e); 193 return null; 194 } 195 finally{ 196 try{ 197 if(Objects.nonNull(is)){ 198 is.close(); 199 } 200 } 201 catch(Exception e2){ 202 LOG.log(Level.SEVERE, "Error closing input stream from " + f, e2); 203 } 204 } 205/* 206URI fileUri = this.cachedResource; 207 if(fileUri == null){ 208 String userHome = System.getProperty("user.home"); 209 File file = new File(userHome + "/.cache", resourceId); 210 if(file.exists()){ 211 fileUri = file.toURI(); 212 } 213 } 214 if(fileUri != null){ 215 File file = new File(fileUri); 216 try( 217 FileInputStream fis = new FileInputStream(file); 218 BufferedInputStream bis = new BufferedInputStream(fis); 219 ObjectInputStream ois = new ObjectInputStream(bis) 220 ){ 221 long loadTS = ois.readLong(); 222 byte[] data = (byte[]) ois.readObject(); 223 this.lastLoaded = loadTS; 224 setData(data); 225 return true; 226 } 227 catch(Exception e){ 228 LOG.log(Level.WARNING, "Failed to read data from cache: " + fileUri, e); 229 } 230 } 231 return false; 232 */ 233 } 234 235 @Override 236 public String toString(){ 237 return "DefaultResourceCache [localDir=" + localDir + ", cachedResources=" + cachedResources + "]"; 238 } 239 240}