/*
* Copyright (c) 2010, the Last.fm Java Project and Committers
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package de.umass.lastfm.cache;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import de.umass.lastfm.scrobble.Scrobbler;
import de.umass.lastfm.scrobble.SubmissionData;
/**
* Standard {@link Cache} implementation which is used by default by the {@link de.umass.lastfm.Caller} class.
* This implementation caches all responses in the file system. In addition to the raw responses it stores a
* .meta file which contains the expiration date for the specified request.
*
* @author Janni Kovacs
*/
@SuppressWarnings({"ALL"})
public class FileSystemCache extends Cache implements ScrobbleCache {
private static final String SUBMISSIONS_FILE = "submissions.txt";
private File cacheDir;
public FileSystemCache() {
this(new File(System.getProperty("user.home") + "/.last.fm-cache"));
}
public FileSystemCache(File cacheDir) {
this.cacheDir = cacheDir;
}
public boolean contains(String cacheEntryName) {
return new File(cacheDir, cacheEntryName + ".xml").exists();
}
public void remove(String cacheEntryName) {
new File(cacheDir, cacheEntryName + ".xml").delete();
new File(cacheDir, cacheEntryName + ".meta").delete();
}
public boolean isExpired(String cacheEntryName) {
File f = new File(cacheDir, cacheEntryName + ".meta");
if (!f.exists())
return false;
try {
Properties p = new Properties();
p.load(new FileInputStream(f));
long expirationDate = Long.valueOf(p.getProperty("expiration-date"));
return expirationDate < System.currentTimeMillis();
} catch (IOException e) {
return false;
}
}
public void clear() {
for (File file : cacheDir.listFiles()) {
if (file.isFile()) {
file.delete();
}
}
}
public InputStream load(String cacheEntryName) {
try {
return new FileInputStream(new File(cacheDir, cacheEntryName + ".xml"));
} catch (FileNotFoundException e) {
return null;
}
}
public void store(String cacheEntryName, InputStream inputStream, long expirationDate) {
createCache();
File f = new File(cacheDir, cacheEntryName + ".xml");
try {
BufferedInputStream is = new BufferedInputStream(inputStream);
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(f));
int read;
byte[] buffer = new byte[4096];
while ((read = is.read(buffer)) != -1) {
os.write(buffer, 0, read);
}
os.close();
is.close();
File fm = new File(cacheDir, cacheEntryName + ".meta");
Properties p = new Properties();
p.setProperty("expiration-date", Long.toString(expirationDate));
p.store(new FileOutputStream(fm), null);
} catch (IOException e) {
// we ignore the exception. if something went wrong we just don't cache it.
}
}
private void createCache() {
if (!cacheDir.exists()) {
cacheDir.mkdirs();
if (!cacheDir.isDirectory()) {
this.cacheDir = cacheDir.getParentFile();
}
}
}
public void cacheScrobble(Collection<SubmissionData> submissions) {
cacheScrobble(submissions.toArray(new SubmissionData[submissions.size()]));
}
public void cacheScrobble(SubmissionData... submissions) {
createCache();
try {
BufferedWriter w = new BufferedWriter(new FileWriter(new File(cacheDir, SUBMISSIONS_FILE), true));
for (SubmissionData submission : submissions) {
w.append(submission.toString());
w.newLine();
}
w.close();
} catch (IOException e) {
// huh ?
// e.printStackTrace();
}
}
public boolean isEmpty() {
File file = new File(cacheDir, SUBMISSIONS_FILE);
if (!file.exists())
return true;
try {
BufferedReader r = new BufferedReader(new FileReader(file));
String line = r.readLine();
r.close();
return line == null || "".equals(line);
} catch (IOException e) {
// huh
// e.printStackTrace();
}
return true;
}
public void scrobble(Scrobbler scrobbler) throws IOException {
File file = new File(cacheDir, SUBMISSIONS_FILE);
if (file.exists()) {
BufferedReader r = new BufferedReader(new FileReader(file));
List<SubmissionData> list = new ArrayList<SubmissionData>(50);
String line;
while ((line = r.readLine()) != null) {
SubmissionData d = new SubmissionData(line);
list.add(d);
if (list.size() == 50) {
scrobbler.submit(list);
list.clear();
}
}
if (list.size() > 0)
scrobbler.submit(list);
r.close();
FileWriter w = new FileWriter(file);
w.close();
}
}
public void clearScrobbleCache() {
File file = new File(cacheDir, SUBMISSIONS_FILE);
file.delete();
}
}