package fitnesse.wiki.zip;
import fitnesse.wiki.NullVersionsController;
import fitnesse.wiki.PageData;
import util.Clock;
import util.StreamReader;
import fitnesse.wiki.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public class ZipFileVersionsController extends NullVersionsController {
public static SimpleDateFormat dateFormat() {
return new SimpleDateFormat("yyyyMMddHHmmss");
}
public ZipFileVersionsController() {
this(new Properties());
}
public ZipFileVersionsController(final Properties properties) {
}
public PageData getRevisionData(final FileSystemPage page, final String label) {
final String filename = getFileSystemPath(page) + "/" + label + ".zip";
final File file = new File(filename);
if (!file.exists()) {
throw new NoSuchVersionException("There is no version '" + label + "'");
}
ZipFile zipFile = null;
try {
final PageData data = new PageData(page);
zipFile = new ZipFile(file);
loadVersionContent(zipFile, data);
loadVersionAttributes(zipFile, data);
data.addVersions(loadVersions(page));
return data;
} catch (Throwable th) {
throw new RuntimeException(th);
} finally {
try {
if (zipFile != null) {
zipFile.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String getFileSystemPath(final FileSystemPage page) {
try {
return page.getFileSystemPath();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Collection<VersionInfo> history(final FileSystemPage page) {
final File dir = new File(getFileSystemPath(page));
final File[] files = dir.listFiles();
final Set<VersionInfo> versions = new HashSet<VersionInfo>();
if (files != null) {
for (final File file : files) {
if (isVersionFile(file)) {
versions.add(new VersionInfo(makeVersionName(file)));
}
}
}
return versions;
}
public boolean isRevisionControlEnabled() {
return true;
}
public boolean isExternalRevisionControlEnabled() {
return false;
}
public VersionInfo makeVersion(final FileSystemPage page, final PageData data) {
final String dirPath = getFileSystemPath(page);
final Set<File> filesToZip = getFilesToZip(dirPath);
final VersionInfo version = makeVersionInfo(data);
if (filesToZip.size() == 0) {
return new VersionInfo("first_commit", "", Clock.currentDate());
}
ZipOutputStream zos = null;
try {
final String filename = makeVersionFileName(page, version.getName());
zos = new ZipOutputStream(new FileOutputStream(filename));
for (File aFilesToZip : filesToZip) {
addToZip(aFilesToZip, zos);
}
return new VersionInfo(version.getName());
} catch (Throwable th) {
throw new RuntimeException(th);
} finally {
try {
if (zos != null) {
zos.finish();
zos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void prune(final FileSystemPage page) {
try {
PageVersionPruner.pruneVersions(page, history(page));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void removeVersion(final FileSystemPage page, final String versionName) {
final String versionFileName = makeVersionFileName(page, versionName);
final File versionFile = new File(versionFileName);
versionFile.delete();
}
private void addToZip(final File file, final ZipOutputStream zos) throws IOException {
final ZipEntry entry = new ZipEntry(file.getName());
zos.putNextEntry(entry);
final FileInputStream is = new FileInputStream(file);
final int size = (int) file.length();
final byte[] bytes = new byte[size];
is.read(bytes);
is.close();
zos.write(bytes, 0, size);
}
private Set<File> getFilesToZip(final String dirPath) {
final Set<File> filesToZip = new HashSet<File>();
final File dir = new File(dirPath);
final File[] files = dir.listFiles();
if (files == null) {
return filesToZip;
}
for (final File file : files) {
if (!(isVersionFile(file) || file.isDirectory())) {
filesToZip.add(file);
}
}
return filesToZip;
}
private boolean isVersionFile(final File file) {
return Pattern.matches("(\\S+)?\\d+\\.zip", file.getName());
}
private void loadVersionAttributes(final ZipFile zipFile, final PageData data) {
final ZipEntry attributes = zipFile.getEntry("properties.xml");
if (attributes != null) {
InputStream attributeIS = null;
try {
attributeIS = zipFile.getInputStream(attributes);
final WikiPageProperties props = new WikiPageProperties(attributeIS);
data.setProperties(props);
} catch (Throwable th) {
throw new RuntimeException(th);
} finally {
try {
if (attributeIS != null) {
attributeIS.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void loadVersionContent(final ZipFile zipFile, final PageData data) {
String content = "";
final ZipEntry contentEntry = zipFile.getEntry("content.txt");
if (contentEntry != null) {
StreamReader reader = null;
try {
final InputStream contentIS = zipFile.getInputStream(contentEntry);
reader = new StreamReader(contentIS);
content = reader.read((int) contentEntry.getSize());
} catch (Throwable th) {
throw new RuntimeException(th);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
data.setContent(content);
}
private Collection<VersionInfo> loadVersions(final FileSystemPage page) {
final File dir = new File(getFileSystemPath(page));
final File[] files = dir.listFiles();
final Set<VersionInfo> versions = new HashSet<VersionInfo>();
if (files != null) {
for (final File file : files) {
if (isVersionFile(file)) {
versions.add(new VersionInfo(makeVersionName(file)));
}
}
}
return versions;
}
private String makeVersionFileName(final FileSystemPage page, final String name) {
return getFileSystemPath(page) + "/" + name + ".zip";
}
private VersionInfo makeVersionInfo(final PageData data) {
try {
Date time;
time = data.getProperties().getLastModificationTime();
String versionName = VersionInfo.nextId() + "-" + dateFormat().format(time);
final String user = data.getAttribute(PageData.LAST_MODIFYING_USER);
if (user != null && !"".equals(user)) {
versionName = user + "-" + versionName;
}
return new VersionInfo(versionName, user, time);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private String makeVersionName(final File file) {
final String name = file.getName();
return name.substring(0, name.length() - 4);
}
@Override
public String toString() {
return this.getClass().getSimpleName();
}
public String getControllerName() {
return "Zipped Version History";
}
}