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.spi.loader;
017
018import javax.money.MonetaryException;
019import java.io.*;
020import java.nio.file.Files;
021import java.util.Map;
022import java.util.concurrent.ConcurrentHashMap;
023import java.util.logging.Level;
024import java.util.logging.Logger;
025
026/**
027 * Default implementation of {@link ResourceCache}, using the local file system.
028 *
029 * @author Anatole Tresch
030 */
031public class DefaultResourceCache implements ResourceCache {
032    /**
033     * The logger used.
034     */
035    private static final Logger LOG = Logger.getLogger(DefaultResourceCache.class.getName());
036    /**
037     * Suffix for files created.
038     */
039    private static final String SUFFIX = ".dat";
040    /**
041     * Local temp directory.
042     */
043    private File localDir = new File(System.getProperty("temp.dir", ".resourceCache"));
044    /**
045     * Cached resources.
046     */
047    private final Map<String, File> cachedResources = new ConcurrentHashMap<>();
048
049    /**
050     * Constructor.
051     */
052    public DefaultResourceCache() {
053        if (!localDir.exists()) {
054            if (!localDir.mkdirs()) {
055                LOG.severe("Error creating cache dir  " + localDir + ", resource cache disabled!");
056                localDir = null;
057            } else {
058                LOG.finest("Created cache dir  " + localDir);
059            }
060        } else if (!localDir.isDirectory()) {
061            LOG.severe("Error initializing cache dir  " + localDir + ", not a directory, resource cache disabled!");
062            localDir = null;
063        } else if (!localDir.canWrite()) {
064            LOG.severe("Error initializing cache dir  " + localDir + ", not writable, resource cache disabled!");
065            localDir = null;
066        }
067        if (localDir!=null) {
068            File[] files = localDir.listFiles();
069            if (files != null) {
070                for (File file : files) {
071                    if (file.isFile()) {
072                        String resourceId = file.getName().substring(0, file.getName().length() - 4);
073                        cachedResources.put(resourceId, file);
074                    }
075                }
076            }
077        }
078    }
079
080    /*
081     * (non-Javadoc)
082     *
083     * @see
084     * org.javamoney.moneta.loader.format.ResourceCache#write(java.lang.String
085     * , byte[])
086     */
087    @Override
088    public void write(String resourceId, byte[] data) {
089        try {
090            File file = this.cachedResources.get(resourceId);
091            if (file==null) {
092                file = new File(localDir, resourceId + SUFFIX);
093                Files.write(file.toPath(), data);
094                this.cachedResources.put(resourceId, file);
095            } else {
096                Files.write(file.toPath(), data);
097            }
098        } catch (Exception e) {
099            LOG.log(Level.WARNING, "Caching of resource failed: " + resourceId, e);
100        }
101    }
102
103    /*
104     * (non-Javadoc)
105     *
106     * @see
107     * org.javamoney.moneta.loader.format.ResourceCache#isCached(java.lang
108     * .String)
109     */
110    @Override
111    public boolean isCached(String resourceId) {
112        return this.cachedResources.containsKey(resourceId);
113    }
114
115    /*
116     * (non-Javadoc)
117     *
118     * @see
119     * org.javamoney.moneta.loader.format.ResourceCache#read(java.lang.String)
120     */
121    @Override
122    public byte[] read(String resourceId) {
123        File f = this.cachedResources.get(resourceId);
124        if (f==null) {
125            return null;
126        }
127        try {
128                        return Files.readAllBytes(f.toPath());
129                } catch (IOException exception) {
130                        throw new MonetaryException("An error on retrieve the resource id: " + resourceId, exception);
131                }
132    }
133
134    @Override
135    public void clear(String resourceId) {
136        File f = this.cachedResources.get(resourceId);
137        if (f != null) {
138            if (f.exists()) {
139                if (!f.delete()) {
140                    LOG.warning("Failed to delete caching file: " + f.getAbsolutePath());
141                }
142            }
143            this.cachedResources.remove(resourceId);
144        }
145    }
146
147    @Override
148    public String toString() {
149        return "DefaultResourceCache [localDir=" + localDir + ", cachedResources=" + cachedResources + ']';
150    }
151
152}