001 package crisp.wbwiki.server; 002 003 import java.beans.XMLDecoder; 004 import java.beans.XMLEncoder; 005 import java.io.File; 006 import java.io.FileInputStream; 007 import java.io.FileOutputStream; 008 import java.io.IOException; 009 import java.io.InputStream; 010 import java.io.OutputStream; 011 012 import org.apache.log4j.Logger; 013 014 import crisp.wbwiki.client.Page; 015 016 /** 017 * Implementation of WikiDb that stores to a text file. 018 * 019 * @author Henrik Kniberg 020 */ 021 public class WikiDbTextFile implements WikiDb { 022 private Logger log = Logger.getLogger(getClass()); 023 private File path; 024 025 /** 026 * @param path Path to the file used to store wiki data (required). 027 */ 028 public WikiDbTextFile(File path) { 029 if (path == null) { 030 throw new IllegalArgumentException("No path provided"); 031 } 032 this.path = path; 033 } 034 035 /** 036 * Path to the file used to store wiki data. Never null. 037 */ 038 public File getPath() { 039 return path; 040 } 041 042 public synchronized Page loadPage() { 043 if (path.exists() && path.length() > 0) { 044 log.debug("Loading from " + path.getAbsolutePath()); 045 InputStream stream = null; 046 try { 047 stream = new FileInputStream(path); 048 XMLDecoder decoder = new XMLDecoder(stream); 049 Page page = (Page) decoder.readObject(); 050 decoder.close(); 051 return page; 052 053 } catch (IOException e) { 054 throw new RuntimeException("Problem while trying to read " + path.getAbsolutePath(), e); 055 } finally { 056 try { 057 stream.close(); 058 } catch (IOException err) { 059 log.error("Error while closing stream. Ignoring it and moving on.", err); 060 } 061 } 062 } else { 063 log.debug("File doesn't exist or is empty: " + path.getAbsolutePath()); 064 065 return new Page(1, ""); 066 } 067 } 068 069 /** 070 * Saves the page and increments the version. 071 * @param pageContent 072 */ 073 public synchronized int savePage(String pageContent) { 074 if (pageContent == null) { 075 pageContent = ""; 076 } 077 int version = getCurrentVersion() + 1; 078 Page newPage = new Page(version, pageContent); 079 080 OutputStream stream = null; 081 try { 082 stream = new FileOutputStream(path, false); 083 XMLEncoder encoder = new XMLEncoder(stream); 084 encoder.writeObject(newPage); 085 encoder.flush(); 086 encoder.close(); 087 return version; 088 } catch (IOException e) { 089 throw new RuntimeException("Problem while trying to write to " + path.getAbsolutePath(), e); 090 } finally { 091 try { 092 stream.close(); 093 } catch (IOException err) { 094 log.error("Error while closing stream. Ignoring it and moving on.", err); 095 } 096 } 097 } 098 099 public synchronized int getCurrentVersion() { 100 //@optimize this should probably be cached 101 return loadPage().getVersion(); 102 } 103 104 }