/* You may freely copy, distribute, modify and use this class as long as the original author attribution remains intact. See message below. Copyright (C) 2003 Christian Pesch. All Rights Reserved. */ package slash.metamusic.util; import java.io.*; import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; /** * A ZipCache maintains a cache archive file, in which it puts * files under a key and returns them when queried with a key. * * @author Christian Pesch */ public class ZipCache { private String cacheFileName; private ZipFile cacheFile = null; public File getCacheDirectory() { throw new UnsupportedOperationException(); } public String getCacheFileName() { return cacheFileName; } public void setCacheFileName(String cacheFileName) { this.cacheFileName = cacheFileName; } protected synchronized boolean existsCacheFile() { if (cacheFile == null) { File file = new File(getCacheFileName()); if (file.exists()) { try { cacheFile = new ZipFile(file); } catch (IOException e) { throw new IllegalArgumentException("Could not create cache file " + file); } } } return cacheFile != null; } public List<File> values() { throw new UnsupportedOperationException(); } protected String replaceForFileName(String fileName) { fileName = fileName.replace(File.separator, ""); return fileName; } public synchronized String getFileAsString(String key) throws IOException { byte[] content = getFileAsBytes(key); return content != null ? new String(content) : null; } public synchronized Object getFileAsObject(String key) throws IOException { byte[] content = getFileAsBytes(key); if (content != null) { ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(content))); try { return ois.readObject(); } catch (ClassNotFoundException e) { System.err.println("Cannot deserialize object"); e.printStackTrace(); } finally { ois.close(); } } return null; } public synchronized byte[] getFileAsBytes(String key) throws IOException { InputStream inputStream = getFileAsInputStream(key); return inputStream != null ? URLLoader.getContents(inputStream) : null; } public synchronized InputStream getFileAsInputStream(String key) throws IOException { key = replaceForFileName(key); if (!existsCacheFile()) return null; ZipEntry entry = cacheFile.getEntry(key); return entry != null ? cacheFile.getInputStream(entry) : null; } public synchronized void putAsString(String key, String value) throws IOException { put(key, value.getBytes()); } public synchronized void putAsObject(String key, Object value) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); try { out.writeObject(value); } finally { out.close(); } put(key, baos.toByteArray()); } public synchronized void put(String key, byte[] value) throws IOException { putAsInputStream(key, new ByteArrayInputStream(value)); } public synchronized void putAsInputStream(String key, InputStream input) throws IOException { key = replaceForFileName(key); File currentFile = new File(getCacheFileName()); File currentDirectory = currentFile.getParentFile(); if (!currentDirectory.exists()) { if (!currentDirectory.mkdirs()) throw new IOException("Could not create cache directory " + currentDirectory); } File newFile = File.createTempFile("newfile", ".zip", currentFile.getParentFile()); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(newFile)); if (existsCacheFile()) { Enumeration<? extends ZipEntry> enumeration = cacheFile.entries(); while (enumeration.hasMoreElements()) { ZipEntry entry = enumeration.nextElement(); out.putNextEntry(entry); out.write(URLLoader.getContents(cacheFile.getInputStream(entry))); } cacheFile.close(); cacheFile = null; } out.putNextEntry(new ZipEntry(key)); out.write(URLLoader.getContents(input)); out.close(); if (currentFile.exists()) { File oldFile = new File(newFile.getAbsolutePath() + ".bak"); if (!currentFile.renameTo(oldFile)) throw new IOException("Could not rename " + currentFile + " to " + oldFile); } if (!newFile.renameTo(currentFile)) throw new IOException("Could not rename " + newFile + " to " + currentFile); } }