| //------------------------------------------------------------------------------ |
| // Copyright (c) 2005, 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 implementation |
| //------------------------------------------------------------------------------ |
| package org.eclipse.epf.persistence; |
| |
| import java.io.File; |
| |
| import org.eclipse.emf.common.CommonPlugin; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.URIConverter; |
| import org.eclipse.epf.common.utils.FileUtil; |
| import org.eclipse.epf.persistence.util.PersistenceResources; |
| import org.eclipse.osgi.util.NLS; |
| |
| /** |
| * @author Phong Nguyen Le |
| * |
| * @since 1.2 |
| */ |
| public class FailSafePersistenceHelper { |
| private URI finalURI; |
| private URI oldURI; |
| private String currentTxID; |
| private Resource resource; |
| private URI tempURI; |
| private String id; |
| private String backupFile; |
| private URIConverter converter; |
| private boolean commitEmptyResource; |
| |
| public FailSafePersistenceHelper(Resource resource, String id) { |
| this.resource = resource; |
| this.id = id; |
| this.converter = resource.getResourceSet() != null ? resource.getResourceSet().getURIConverter() : null; |
| } |
| |
| public void setCommitEmptyResource(boolean commitEmptyResource) { |
| this.commitEmptyResource = commitEmptyResource; |
| } |
| |
| /** |
| * Sets the temporary URI to save this resource to and it will be renamed to |
| * the original URI when saving is done |
| */ |
| public URI setTempURI(String txID) { |
| if (finalURI == null) { |
| finalURI = oldURI = resource.getURI(); |
| currentTxID = txID; |
| |
| tempURI = createTempURI(); |
| resource.setURI(tempURI); |
| } |
| return tempURI; |
| } |
| |
| private URI createTempURI() { |
| return URI.createFileURI(new StringBuffer(MultiFileXMIResourceImpl.getTempDir()).append( |
| File.separator).append(currentTxID) |
| .append("new").append(id).toString()); //$NON-NLS-1$ |
| } |
| |
| public String getBackupFilePath() { |
| String backupFile = new StringBuffer(MultiFileXMIResourceImpl.getTempDir()) |
| .append(File.separator) |
| .append(currentTxID) |
| .append("old").append(id).toString(); //$NON-NLS-1$ |
| return backupFile; |
| } |
| |
| private String toFileString(URI uri) { |
| return FileManager.toFileString(uri, converter); |
| } |
| |
| public void commit() { |
| if (finalURI != null && (commitEmptyResource || !resource.getContents().isEmpty())) { |
| File finalFile = new File(toFileString(finalURI)); |
| boolean wasMove = !oldURI.equals(finalURI); |
| if (wasMove) { |
| } else { |
| // back up the file |
| // |
| String backup = getBackupFilePath(); |
| File bakFile = new File(backup); |
| |
| // trying to delete the old backup file if it exists |
| // |
| if (bakFile.exists()) { |
| bakFile.delete(); |
| } |
| |
| if (finalFile.exists()) { |
| // some CM provider like ClearCase renamed the versioned |
| // file it its repository as soon as user renamed the file |
| // in the workspace. To avoid this, use only regular rename |
| // routine of java.io.File instead of IResource routine |
| // |
| if (FileUtil.moveFile(finalFile, bakFile)) { |
| backupFile = backup; |
| } else { |
| String msg = NLS.bind( |
| PersistenceResources.renameError_msg, |
| finalFile, backup); |
| throw new MultiFileIOException(msg); |
| } |
| } |
| } |
| |
| // rename the resource file to the original name |
| // |
| File currentFile = new File(wasMove ? toFileString(oldURI) |
| : toFileString(resource.getURI())); |
| boolean success = false; |
| if (wasMove) { |
| success = MultiFileSaveUtil.move(resource, currentFile, finalFile); |
| } else { |
| // some CM provider like ClearCase renamed the versioned file it |
| // its repository as soon as user renamed the file |
| // in the workspace. To avoid this, use only regular rename |
| // routine of java.io.File instead of IResource routine |
| // |
| success = FileUtil.moveFile(currentFile, finalFile); |
| } |
| if (!success) { |
| String msg = NLS.bind(PersistenceResources.renameError_msg, |
| currentFile, finalFile); |
| throw new MultiFileIOException(msg); |
| } else { |
| if (wasMove) { |
| didMove(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Subclass to override to handle post move |
| */ |
| protected void didMove() { |
| } |
| |
| public void deleteBackup() { |
| if (backupFile != null) { |
| try { |
| // FileManager.getInstance().delete(backupFile); |
| new File(backupFile).delete(); |
| backupFile = null; |
| } catch (Throwable e) { |
| CommonPlugin.INSTANCE.log(e); |
| if (MultiFileSaveUtil.DEBUG) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| |
| public boolean hasTempURI() { |
| if (currentTxID != null) { |
| return createTempURI().equals(resource.getURI()); |
| } |
| return false; |
| } |
| |
| public URI getFinalURI() { |
| if (finalURI != null) { |
| return finalURI; |
| } |
| return resource.getURI(); |
| } |
| |
| public boolean restore() { |
| File src = null, dest = null; |
| boolean moved = false; |
| if (backupFile != null) { |
| src = new File(backupFile); |
| dest = new File(toFileString(getFinalURI())); |
| } else { |
| moved = oldURI != null && !oldURI.equals(finalURI); |
| if (moved) { |
| File file = new File(toFileString(getFinalURI())); |
| dest = new File(toFileString(oldURI)); |
| moved = file.exists() && !dest.exists(); |
| if (moved) { |
| src = file; |
| } |
| } |
| } |
| if (src != null) { |
| if (dest.exists()) { |
| FileUtil.moveFile(dest,new File(toFileString(resource.getURI()))); |
| } |
| boolean success; |
| if (moved) { |
| success = MultiFileSaveUtil.move(resource, src, dest); |
| // if(success) { |
| // MultiFileSaveUtil.updateURIMappings(this, null); |
| // } |
| } else { |
| success = FileUtil.moveFile(src,dest); |
| } |
| if (!success) { |
| throw new MultiFileIOException(NLS.bind( |
| PersistenceResources.restoreResourceError_msg, this)); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| public void txFinished(boolean successful) { |
| if (successful) { |
| resource.setURI(finalURI); |
| resource.setModified(false); |
| FileManager.getInstance().refresh(resource); |
| } else { |
| restoreURI(); |
| } |
| currentTxID = null; |
| finalURI = null; |
| } |
| |
| /** |
| * Restores the resource URI to the original one. This method must be call |
| * after saving regarless of its success. |
| * |
| */ |
| private void restoreURI() { |
| if (oldURI != null) { |
| resource.setURI(oldURI); |
| } |
| } |
| |
| } |