001: // Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
002: // Released under the terms of the GNU General Public License version 2 or later.
003: package fitnesse.wiki;
004:
005: import fitnesse.util.*;
006: import fitnesse.wikitext.widgets.WikiWordWidget;
007:
008: import java.io.*;
009: import java.text.SimpleDateFormat;
010: import java.util.*;
011: import java.util.regex.Pattern;
012: import java.util.zip.*;
013:
014: public class FileSystemPage extends CachingPage {
015: public static final String contentFilename = "/content.txt";
016: public static final String propertiesFilename = "/properties.xml";
017:
018: private String path;
019:
020: protected FileSystemPage(String path, String name, WikiPage parent)
021: throws Exception {
022: super (name, parent);
023: this .path = path;
024: }
025:
026: public static WikiPage makeRoot(String path, String name)
027: throws Exception {
028: return new FileSystemPage(path, name, null);
029: }
030:
031: public void removeChildPage(String name) throws Exception {
032: super .removeChildPage(name);
033: File fileToBeDeleted = new File(getFileSystemPath() + "/"
034: + name);
035: FileUtil.deleteFileSystemDirectory(fileToBeDeleted);
036: }
037:
038: public boolean hasChildPage(String pageName) throws Exception {
039: File f = new File(getFileSystemPath() + "/" + pageName);
040: if (f.exists()) {
041: addChildPage(pageName);
042: return true;
043: } else
044: return false;
045: }
046:
047: protected synchronized void saveContent(String content)
048: throws Exception {
049: if (content == null)
050: return;
051:
052: String separator = System.getProperty("line.separator");
053:
054: if (content.endsWith("|"))
055: content += separator;
056:
057: content = content.replaceAll("\r\n", separator);
058:
059: File output = new File(getFileSystemPath() + contentFilename);
060: OutputStreamWriter writer = new OutputStreamWriter(
061: new FileOutputStream(output), "UTF-8");
062: writer.write(content);
063: writer.close();
064: }
065:
066: protected synchronized void saveAttributes(
067: WikiPageProperties attributes) throws Exception {
068: String propertiesFileName = getFileSystemPath()
069: + propertiesFilename;
070: OutputStream output = new FileOutputStream(propertiesFileName);
071: attributes.save(output);
072: output.close();
073: }
074:
075: protected WikiPage createChildPage(String name) throws Exception {
076: FileSystemPage newPage = new FileSystemPage(
077: getFileSystemPath(), name, this );
078: new File(newPage.getFileSystemPath()).mkdirs();
079: return newPage;
080: }
081:
082: private void loadContent(PageData data) throws Exception {
083: String content = "";
084:
085: String name = getFileSystemPath() + contentFilename;
086: File input = new File(name);
087: if (input.exists()) {
088: byte[] bytes = new byte[(int) input.length()];
089: FileInputStream inputStream = new FileInputStream(input);
090: inputStream.read(bytes);
091: inputStream.close();
092:
093: content = new String(bytes, "UTF-8");
094: }
095: data.setContent(content);
096: }
097:
098: protected void loadChildren() throws Exception {
099: File this Dir = new File(getFileSystemPath());
100: if (this Dir.exists()) {
101: String[] subFiles = this Dir.list();
102: for (int i = 0; i < subFiles.length; i++) {
103: String subFile = subFiles[i];
104: if (fileIsValid(subFile, this Dir)
105: && !children.containsKey(subFile))
106: children.put(subFile, getChildPage(subFile));
107: }
108: }
109: }
110:
111: private boolean fileIsValid(String filename, File dir) {
112: if (WikiWordWidget.isWikiWord(filename)) {
113: File f = new File(dir, filename);
114: if (f.isDirectory())
115: return true;
116: }
117: return false;
118: }
119:
120: private String getParentFileSystemPath() throws Exception {
121: return (parent != null) ? ((FileSystemPage) parent)
122: .getFileSystemPath() : path;
123: }
124:
125: public String getFileSystemPath() throws Exception {
126: return getParentFileSystemPath() + "/" + getName();
127: }
128:
129: private void loadAttributes(PageData data) throws Exception {
130: File file = new File(getFileSystemPath() + propertiesFilename);
131: if (file.exists()) {
132: try {
133: attemptToReadPropertiesFile(file, data);
134: } catch (Exception e) {
135: System.err.println("Could not read properties file:"
136: + file.getPath());
137: e.printStackTrace();
138: }
139: }
140: }
141:
142: private void attemptToReadPropertiesFile(File file, PageData data)
143: throws Exception {
144: WikiPageProperties props = new WikiPageProperties();
145: InputStream input = new FileInputStream(file);
146: props.loadFromXmlStream(input);
147: input.close();
148: data.setProperties(props);
149: }
150:
151: public void doCommit(PageData data) throws Exception {
152: data.getProperties().setLastModificationTime(new Date());
153: saveContent(data.getContent());
154: saveAttributes(data.getProperties());
155: PageVersionPruner.pruneVersions(this , loadVersions());
156: }
157:
158: protected PageData makePageData() throws Exception {
159: PageData pagedata = new PageData(this );
160: loadContent(pagedata);
161: loadAttributes(pagedata);
162: pagedata.addVersions(loadVersions());
163: return pagedata;
164: }
165:
166: public PageData getDataVersion(String versionName) throws Exception {
167: String filename = getFileSystemPath() + "/" + versionName
168: + ".zip";
169: File file = new File(filename);
170: if (!file.exists())
171: throw new NoSuchVersionException("There is no version '"
172: + versionName + "'");
173:
174: PageData data = new PageData(this );
175: ZipFile zipFile = new ZipFile(file);
176: loadVersionContent(zipFile, data);
177: loadVersionAttributes(zipFile, data);
178: data.addVersions(loadVersions());
179: zipFile.close();
180: return data;
181: }
182:
183: private Collection loadVersions() throws Exception {
184: File dir = new File(getFileSystemPath());
185: File[] files = dir.listFiles();
186: Set<VersionInfo> versions = new HashSet<VersionInfo>();
187: if (files != null) {
188: for (int i = 0; i < files.length; i++) {
189: File file = files[i];
190: if (isVersionFile(file))
191: versions
192: .add(new VersionInfo(makeVersionName(file)));
193: }
194: }
195: return versions;
196: }
197:
198: protected VersionInfo makeVersion() throws Exception {
199: PageData data = getData();
200: return makeVersion(data);
201: }
202:
203: protected VersionInfo makeVersion(PageData data) throws Exception {
204: String dirPath = getFileSystemPath();
205: Set filesToZip = getFilesToZip(dirPath);
206:
207: VersionInfo version = makeVersionInfo(data);
208:
209: if (filesToZip.size() == 0)
210: return new VersionInfo("first_commit", "", new Date());
211:
212: String filename = makeVersionFileName(version.getName());
213: ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(
214: filename));
215:
216: for (Iterator iterator = filesToZip.iterator(); iterator
217: .hasNext();)
218: addToZip((File) iterator.next(), zos);
219:
220: zos.finish();
221: zos.close();
222: return new VersionInfo(version.getName());
223: }
224:
225: protected VersionInfo makeVersionInfo(PageData data)
226: throws Exception {
227: Date time = data.getProperties().getLastModificationTime();
228: String versionName = VersionInfo.nextId() + "-"
229: + dateFormat().format(time);
230: String user = data.getAttribute(WikiPage.LAST_MODIFYING_USER);
231: if (user != null && !"".equals(user))
232: versionName = user + "-" + versionName;
233:
234: return new VersionInfo(versionName, user, time);
235: }
236:
237: public static SimpleDateFormat dateFormat() {
238: return new SimpleDateFormat("yyyyMMddHHmmss");
239: }
240:
241: protected String makeVersionFileName(String name) throws Exception {
242: return getFileSystemPath() + "/" + name + ".zip";
243: }
244:
245: protected String makeVersionName(File file) {
246: String name = file.getName();
247: return name.substring(0, name.length() - 4);
248: }
249:
250: protected boolean isVersionFile(File file) {
251: return Pattern.matches("(\\S+)?\\d+\\.zip", file.getName());
252: }
253:
254: protected void removeVersion(String versionName) throws Exception {
255: String versionFileName = makeVersionFileName(versionName);
256: File versionFile = new File(versionFileName);
257: versionFile.delete();
258: }
259:
260: protected Set getFilesToZip(String dirPath) {
261: Set<File> filesToZip = new HashSet<File>();
262: File dir = new File(dirPath);
263: File[] files = dir.listFiles();
264: if (files == null)
265: return filesToZip;
266: for (int i = 0; i < files.length; i++) {
267: File file = files[i];
268: if (!(isVersionFile(file) || file.isDirectory()))
269: filesToZip.add(file);
270: }
271: return filesToZip;
272: }
273:
274: private void addToZip(File file, ZipOutputStream zos)
275: throws IOException {
276: ZipEntry entry = new ZipEntry(file.getName());
277: zos.putNextEntry(entry);
278: FileInputStream is = new FileInputStream(file);
279: int size = (int) file.length();
280: byte[] bytes = new byte[size];
281: is.read(bytes);
282: is.close();
283: zos.write(bytes, 0, size);
284: }
285:
286: protected void loadVersionContent(ZipFile zipFile, PageData data)
287: throws Exception {
288: String content = "";
289: ZipEntry contentEntry = zipFile.getEntry("content.txt");
290: if (contentEntry != null) {
291: InputStream contentIS = zipFile
292: .getInputStream(contentEntry);
293: StreamReader reader = new StreamReader(contentIS);
294: content = reader.read((int) contentEntry.getSize());
295: reader.close();
296: }
297: data.setContent(content);
298: }
299:
300: protected void loadVersionAttributes(ZipFile zipFile, PageData data)
301: throws Exception {
302: ZipEntry attributes = zipFile.getEntry("properties.xml");
303: if (attributes != null) {
304: InputStream attributeIS = zipFile
305: .getInputStream(attributes);
306: WikiPageProperties props = new WikiPageProperties(
307: attributeIS);
308: attributeIS.close();
309: data.setProperties(props);
310: }
311: }
312:
313: public String toString() {
314: try {
315: return getClass().getName() + " at "
316: + this .getFileSystemPath();
317: } catch (Exception e) {
318: return super.toString();
319: }
320: }
321: }
|