Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/prov/touchpoint/natives/BackupFiles.java')
-rw-r--r--bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/prov/touchpoint/natives/BackupFiles.java319
1 files changed, 319 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/prov/touchpoint/natives/BackupFiles.java b/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/prov/touchpoint/natives/BackupFiles.java
new file mode 100644
index 000000000..7c47ebb7b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.touchpoint.natives/src/org/eclipse/equinox/internal/prov/touchpoint/natives/BackupFiles.java
@@ -0,0 +1,319 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.prov.touchpoint.natives;
+
+import java.io.*;
+import java.net.URL;
+import java.util.*;
+import java.util.zip.*;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.equinox.prov.core.helpers.FileUtils;
+import org.eclipse.osgi.util.NLS;
+
+public class BackupFiles {
+
+ private static final String ZIP_SUFFIX = ".zip"; //$NON-NLS-1$
+ private static final String PROPERTIES_SUFFIX = ".properties"; //$NON-NLS-1$
+
+ private final File backupDir;
+ private boolean doBackup;
+
+ /**
+ * Save or restore backups of files in backupDir
+ */
+ public BackupFiles(File backupDir) {
+ this.doBackup = true;
+ this.backupDir = backupDir;
+ this.backupDir.mkdirs();
+ }
+
+ // /**
+ // * If doBackup is set to false, files are deleted on uninstall, instead of restored.
+ // */
+ // public void setDoBackup(boolean doBackup) {
+ // this.doBackup = doBackup;
+ // }
+
+ /**
+ * Restore all backups made in this dir.
+ */
+ public void restore(IProgressMonitor monitor) throws IOException {
+ // find backup properties files, do in reverse order
+ List propsFiles = new LinkedList();
+ for (int i = 0;; i += 1) {
+ File propsFile = getBackupProperties(i);
+ if (!propsFile.exists()) {
+ break;
+ }
+ propsFiles.add(0, propsFile);
+ }
+ IProgressMonitor[] pm = Util.splitProgressMonitor(monitor, propsFiles.size());
+ int j = 0;
+ for (Iterator i = propsFiles.iterator(); i.hasNext();) {
+ File propsFile = (File) i.next();
+ restoreFilesFromBackup(propsFile, pm[j++]);
+ }
+ if (!this.backupDir.delete()) {
+ //not empty? log a warning?
+ } else {
+ // delete the parent if empty
+ this.backupDir.getParentFile().delete();
+ }
+ monitor.done();
+ }
+
+ /**
+ * Find files under outputDir that will be overwritten in unzipURL
+ * and save under backupDir, and delete.
+ * Include properties file to indicate files to delete or restore on rolled back.
+ * The progress monitor is used only to display sub-tasks; we don't update it otherwise.
+ */
+ public void backupFilesInZip(String identifier, URL zipURL, File outputDir, IProgressMonitor monitor) throws IOException {
+ BackupProperties backupProps = new BackupProperties(identifier, outputDir);
+ ZipOutputStream zos = null;
+ String prevDir = null;
+ try {
+ ZipInputStream in = new ZipInputStream(zipURL.openStream());
+ ZipEntry ze;
+ while ((ze = in.getNextEntry()) != null) {
+ String name = ze.getName();
+ int i = name.lastIndexOf('/');
+ if (i != -1) {
+ String dir = name.substring(0, i);
+ if (this.doBackup && !dir.equals(prevDir)) {
+ monitor.subTask(name.substring(0, i));
+ prevDir = dir;
+ }
+ }
+ if (!ze.isDirectory()) {
+ File origFile = new File(outputDir, name);
+ if (this.doBackup && origFile.exists()) {
+ if (zos == null) {
+ File zipFile = backupProps.getArchive();
+ zos = new ZipOutputStream(new FileOutputStream(zipFile));
+ }
+ ZipEntry zipEntry = new ZipEntry(name);
+ zipEntry.setTime(origFile.lastModified());
+ zos.putNextEntry(zipEntry);
+ FileUtils.copyStream(new FileInputStream(origFile), true, zos, false);
+ zos.closeEntry();
+ } else {
+ backupProps.addFileToDelete(name);
+ }
+ origFile.delete();
+ }
+ in.closeEntry();
+ }
+ in.close();
+ } finally {
+ backupProps.store();
+ if (zos != null) {
+ zos.close();
+ }
+ }
+ }
+
+ private void restoreFilesFromBackup(File propsFile, IProgressMonitor monitor) throws IOException {
+ BackupProperties backupProps = new BackupProperties(propsFile);
+ monitor.beginTask(NLS.bind(Messages.restoring, propsFile.toString()), 3);
+ monitor.subTask("");
+ for (Iterator i = backupProps.getFilesToDelete().iterator(); i.hasNext();) {
+ String name = (String) i.next();
+ File full = new File(backupProps.getRootDir(), name);
+ full.delete();
+ }
+ monitor.worked(1);
+ File zipFile = backupProps.getArchive();
+ if (zipFile.exists()) { // only exists if files were saved
+ SubProgressMonitor sub = new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+ FileUtils.unzipFile(zipFile, backupProps.getRootDir(), "", sub);
+ zipFile.delete();
+ } else {
+ monitor.worked(1);
+ }
+ for (Iterator i = backupProps.getDirsToDelete().iterator(); i.hasNext();) {
+ String name = (String) i.next();
+ File full = new File(backupProps.getRootDir(), name);
+ FileUtils.deleteEmptyDirs(full);
+ }
+ propsFile.delete();
+ monitor.worked(1);
+ monitor.done();
+ }
+
+ // Backup files are just 0.properties, 1.properties, etc.
+ // Get the next unused one.
+ private File getBackupProperties() {
+ for (int i = 0;; i += 1) {
+ File result = getBackupProperties(i);
+ if (!result.exists())
+ return result;
+ }
+ }
+
+ private File getBackupProperties(int i) {
+ return new File(BackupFiles.this.backupDir, Integer.toString(i) + PROPERTIES_SUFFIX);
+ }
+
+ private class BackupProperties extends Properties {
+ private static final long serialVersionUID = 2268313492348533029L;
+ private static final char FILE_KIND = 'f';
+ private static final char DIR_KIND = 'd';
+ private static final String ROOT_DIR = "rootDir"; //$NON-NLS-1$
+ private static final String ARTIFACT_KEY = "artifactKey"; //$NON-NLS-1$
+ // private static final String ARTIFACT_USER = "artifactUser"; //$NON-NLS-1$
+
+ private int n = 0; // number of properties
+ private File file; // file to store properties in
+ private List keys = new LinkedList(); // keys, in order they were added or read
+ private final File rootDir; // root of where files are going
+ private Set dirsToCreate = new TreeSet(); // set of dirs we will create
+
+ // create properties based on file we are backing up to
+ public BackupProperties(String identifier, File rootDir) {
+ this.file = BackupFiles.this.getBackupProperties();
+ this.rootDir = rootDir;
+ setProperty(ROOT_DIR, rootDir.getPath().replace('\\', '/'));
+ setProperty(ARTIFACT_KEY, (identifier != null ? identifier : rootDir.getAbsolutePath()));
+ // setProperty(ARTIFACT_USER, artifact.toUserString());
+ // make sure rootDir is deleted if appropriate
+ addDir("./"); //$NON-NLS-1$
+ }
+
+ // create backup properties from a previously saved BackupProperties
+ public BackupProperties(File file) throws IOException {
+ this.file = file;
+ FileInputStream stream = new FileInputStream(file);
+ try {
+ load(stream);
+ } finally {
+ stream.close();
+ }
+ this.rootDir = new File(getProperty(ROOT_DIR));
+ }
+
+ // public String getArtifactKey() {
+ // return getProperty(ARTIFACT_KEY);
+ // }
+
+ // public String getArtifactUserString() {
+ // String result = getProperty(ARTIFACT_USER);
+ // if (result != null) {
+ // return result;
+ // } else {
+ // // return something if the key wasn't saved
+ // result = getArtifactKey();
+ // result = result.replaceFirst(",native,", ","); //$NON-NLS-1$ //$NON-NLS-2$
+ // return result.replace(',', ' ').trim();
+ // }
+ // }
+
+ public File getRootDir() {
+ return this.rootDir;
+ }
+
+ // We are backing up files for this artifact.
+ // Create a backup zip based on the artifact key (as a hint).
+ public File getArchive() {
+ String path = this.file.getPath();
+ if (path.endsWith(PROPERTIES_SUFFIX)) {
+ path = path.substring(0, path.length() - PROPERTIES_SUFFIX.length());
+ }
+ return new File(path + ZIP_SUFFIX);
+ }
+
+ public List getFilesToDelete() {
+ return getMatchingProperties(FILE_KIND);
+ }
+
+ public List getDirsToDelete() {
+ return getMatchingProperties(DIR_KIND);
+ }
+
+ private List getMatchingProperties(char c) {
+ List result = new LinkedList();
+ for (Enumeration e = propertyNames(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ if (key.equals(BackupProperties.ROOT_DIR)) {
+ continue;
+ }
+ if (key.charAt(0) == c) {
+ result.add(getProperty(key));
+ }
+ }
+ return result;
+ }
+
+ public void addFileToDelete(String name) {
+ add(FILE_KIND, name);
+ addDir(name);
+ }
+
+ public void store() throws IOException {
+ // add the directories -- at end because we want them all in order
+ for (Iterator i = this.dirsToCreate.iterator(); i.hasNext();) {
+ String name = (String) i.next();
+ add(DIR_KIND, name);
+ }
+ FileOutputStream stream = new FileOutputStream(this.file);
+ try {
+ store(stream, /*header*/null);
+ } finally {
+ stream.close();
+ }
+ }
+
+ public Object put(Object key, Object value) {
+ if (!(key instanceof String))
+ throw new AssertionError("expected String: " + key); //$NON-NLS-1$
+ if (!(value instanceof String))
+ throw new AssertionError("expected String: " + value); //$NON-NLS-1$
+ this.keys.add(key);
+ return super.put(key, value);
+ }
+
+ // return keys in the order they were added
+ public synchronized Enumeration keys() {
+ final Iterator iterator = this.keys.iterator();
+ return new Enumeration() {
+ public boolean hasMoreElements() {
+ return iterator.hasNext();
+ }
+
+ public Object nextElement() {
+ return iterator.next();
+ }
+ };
+ }
+
+ private void add(char kind, String name) {
+ StringBuffer key = new StringBuffer(4);
+ key.append(kind).append(n++);
+ setProperty(key.toString(), name.replace('\\', '/'));
+ }
+
+ // if we're going to create this dir, remember that so we delete it
+ private void addDir(String name) {
+ int slash = name.lastIndexOf('/');
+ if (slash == -1)
+ return; // no dir
+ String dirName = name.substring(0, slash);
+ if (this.dirsToCreate.contains(dirName))
+ return; // already have it
+ if (new File(this.rootDir, dirName).exists())
+ return; // already exists
+ this.dirsToCreate.add(dirName);
+ }
+
+ }
+
+}

Back to the top