blob: 5297b61e03a99a346483057b29285cf96846cbdc [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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 java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.eclipse.core.resources.IResource;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMLHelper;
import org.eclipse.emf.ecore.xmi.XMLLoad;
import org.eclipse.emf.ecore.xmi.XMLSave;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.library.persistence.ILibraryResource;
import org.eclipse.epf.library.persistence.internal.IFailSafeSavable;
import org.eclipse.epf.persistence.refresh.RefreshJob;
import org.eclipse.epf.persistence.util.PersistenceResources;
import org.eclipse.epf.persistence.util.PersistenceUtil;
import org.eclipse.epf.resourcemanager.ResourceDescriptor;
import org.eclipse.epf.resourcemanager.ResourceManager;
import org.eclipse.epf.services.ILibraryPersister;
import org.eclipse.epf.uma.ContentDescription;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.Section;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.ecore.util.DefaultValueManager;
import org.eclipse.epf.uma.ecore.util.OppositeFeatureNotification;
import org.eclipse.osgi.util.NLS;
/**
* Resource implementation for library XMI persistence
*
* @author Phong Nguyen Le
* @since 1.0
*/
public class MultiFileXMIResourceImpl extends XMIResourceImpl
implements ILibraryResource, IFailSafeSavable
{
private static String tempDir;
private URI finalURI;
private URI oldURI;
private String backupFile;
private String currentTxID;
private long lastLoadTimeStamp;
private ResourceDescriptor resourceDescriptor;
private boolean isUnloading;
/** Cached modification stamp of the resource file */
private long modificationStamp;
private IFileInfo fileInfo;
public MultiFileXMIResourceImpl(URI uri) {
super(uri);
setIntrinsicIDToEObjectMap(new HashMap());
}
protected XMLLoad createXMLLoad() {
return new MultiFileXMILoadImpl(createXMLHelper());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#createXMLSave()
*/
protected XMLSave createXMLSave() {
return new MultiFileXMISaveImpl(createXMLHelper());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl#createXMLHelper()
*/
protected XMLHelper createXMLHelper() {
return new MultiFileXMIHelperImpl(this);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.xmi.XMLResource#getID(org.eclipse.emf.ecore.EObject)
*/
public String getID(EObject eObject) {
String id = MultiFileSaveUtil.getGuid(eObject);
if (id != null)
return id;
return super.getID(eObject);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#setID(org.eclipse.emf.ecore.EObject,
* java.lang.String)
*/
public void setID(EObject eObject, String id) {
Object oldID = id != null ? getEObjectToIDMap().put(eObject, id)
: getEObjectToIDMap().remove(eObject);
Map guidToMethodElementMap = ((MultiFileResourceSetImpl) getResourceSet())
.getGuidToMethodElementMap();
if (oldID != null) {
getIDToEObjectMap().remove(oldID);
if (eObject instanceof MethodElement) {
// remove object from guidToMethodElementMap only if it is a proxy
//
if(eObject.eIsProxy()) {
EObject obj = (EObject) guidToMethodElementMap.get(id);
if(obj != null && obj.eIsProxy()) {
guidToMethodElementMap.remove(id);
}
}
else {
guidToMethodElementMap.remove(id);
}
}
}
if (id != null) {
getIDToEObjectMap().put(id, eObject);
if (eObject instanceof MethodElement) {
guidToMethodElementMap.put(id, eObject);
MethodElement e = (MethodElement) eObject;
if (!e.getGuid().equals(id)) {
e.setGuid(id);
}
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#useUUIDs()
*/
protected boolean useUUIDs() {
return true;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.resource.Resource#getURIFragment(org.eclipse.emf.ecore.EObject)
*/
public String getURIFragment(EObject eObject) {
try {
String id = getID(eObject);
if (id != null) {
return id;
} else {
List uriFragmentPath = new ArrayList();
for (EObject container = eObject.eContainer(); container != null
&& container.eResource() == this; container = eObject
.eContainer()) {
uriFragmentPath.add(((InternalEObject) container)
.eURIFragmentSegment(eObject.eContainingFeature(),
eObject));
eObject = container;
}
StringBuffer result = new StringBuffer("/"); //$NON-NLS-1$
result.append(getURIFragmentRootSegment(eObject));
for (ListIterator i = uriFragmentPath
.listIterator(uriFragmentPath.size()); i.hasPrevious();) {
result.append('/');
result.append((String) i.previous());
}
return result.toString();
}
} catch (RuntimeException e) {
System.err.println("Error getting URI fragment for " + eObject); //$NON-NLS-1$
throw e;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#attachedHelper(org.eclipse.emf.ecore.EObject)
*/
protected void attachedHelper(EObject eObject) {
super.attachedHelper(eObject);
if (useIDs()) {
String id = getID(eObject);
if (id != null) {
// update the eObjectToIDMap
//
getEObjectToIDMap().put(eObject, id);
if (eObject instanceof MethodElement) {
((MultiFileResourceSetImpl) getResourceSet())
.getGuidToMethodElementMap().put(id, eObject);
}
}
}
if (isTrackingModification() && eObject.eResource() != this) {
// remove the modification tracking adapter from the eObject
//
eObject.eAdapters().remove(modificationTrackingAdapter);
}
}
private void attachedAllWithIDs(EObject eObj) {
// attachedHelper(eObj);
// List list = eObj.eContents();
// int size = list.size();
// for (int i = 0; i < size; i++) {
// EObject o = (EObject) list.get(i);
// if (o.eResource() == this) {
// attachedAllWithIDs(o);
// }
// }
Iterator allContents = new ContentTreeIterator(eObj);
while (allContents.hasNext()) {
attachedHelper((EObject) allContents.next());
}
}
private void basicAttachedAll(EObject eObj) {
eObj.eAdapters().add(modificationTrackingAdapter);
List list = eObj.eContents();
int size = list.size();
for (int i = 0; i < size; i++) {
EObject o = (EObject) list.get(i);
if (o.eResource() == this) {
basicAttachedAll(o);
}
}
}
/**
* Calls on an object and all of its offstring objects that are in the same
* resource as the object when the object is attached to this resource. This
* method is expensive, so use it with caution.
*
* @param eObj
*/
public void attachedAll(EObject eObj) {
if (useIDs()) {
attachedAllWithIDs(eObj);
} else {
basicAttachedAll(eObj);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.resource.Resource.Internal#attached(org.eclipse.emf.ecore.EObject)
*/
public void attached(EObject eObject) {
attachedAll(eObject);
}
private void detachedAllWithIDs(EObject eObj) {
Iterator allContents = new ContentTreeIterator(eObj);
while (allContents.hasNext()) {
detachedHelper((EObject) allContents.next());
}
}
private void basicDetachedAll(EObject eObj) {
eObj.eAdapters().remove(modificationTrackingAdapter);
List list = eObj.eContents();
int size = list.size();
for (int i = 0; i < size; i++) {
EObject o = (EObject) list.get(i);
if (o.eResource() == this) {
basicDetachedAll(o);
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#getEObjectByID(java.lang.String)
*/
protected EObject getEObjectByID(String id) {
for (Iterator iter = getContents().iterator(); iter.hasNext();) {
EObject element = (EObject) iter.next();
String guid = MultiFileSaveUtil.getGuid(element);
if (guid != null && guid.equals(id))
return element;
}
// return super.getEObjectByID(id);
if (idToEObjectMap != null) {
InternalEObject eObject = (InternalEObject) idToEObjectMap.get(id);
if (eObject != null && !eObject.eIsProxy()) {
return eObject;
}
}
return null;
}
private IFileInfo getFileInfo() {
if(fileInfo == null || !new File(getURI().toFileString()).equals(fileInfo.getFile())) {
fileInfo = FileManager.getInstance().getFileInfo(this);
}
return fileInfo;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.resource.impl.ResourceImpl#load(java.util.Map)
*/
public void load(Map options) throws IOException {
if (isUnloading) {
return;
}
boolean old = DefaultValueManager.INSTANCE.isUseStatic();
try {
DefaultValueManager.INSTANCE.setUseStatic(true);
super.load(options);
updateTimeStamps();
}
finally {
DefaultValueManager.INSTANCE.setUseStatic(old);
}
if (MultiFileSaveUtil.DEBUG) {
if (getURI().toString().equals(testResourceURIStr)) {
testResourceLoaded = true;
}
}
}
private static boolean testResourceLoaded;
private static final String testResourceURIStr = "file:/C:/temp/newlib/library.xmi"; //$NON-NLS-1$
public long getModificationStamp() {
return modificationStamp;
}
/**
* Reloads this resource. Old objects will become proxies and they will be
* added to the specified collection <code>proxies</code>
*
* @param proxies
*/
synchronized boolean reload(Collection proxies) throws IOException {
if (isLoaded) {
Notification notification = setLoaded(false);
doUnload(proxies, false);
// doUnload() might have set this resource loaded again
// set isLoaded to false and contents to null to make sure
//
isLoaded = false;
contents = null;
if (notification != null) {
eNotify(notification);
}
load(getResourceSet().getLoadOptions());
return true;
}
return false;
}
/*
* Javadoc copied from interface.
*/
final void unloadWithoutRemove() {
if (isLoaded) {
// save the ResourceDescriptor pf this resource for later use to
// create URI for the proxies after unload
//
ResourceDescriptor resDesc = MultiFileSaveUtil
.getResourceDescriptor(this);
if (resDesc != null) {
setResourceDescriptor(resDesc);
}
Notification notification = setLoaded(false);
doUnload(null, false);
if (notification != null) {
eNotify(notification);
}
}
}
/**
* Does all the work of unloading the resource. It calls
* {@link #unloaded unloaded} for each object it the content
* {@link #getAllContents tree}, and clears the
* {@link #getContents contents}, {@link #getErrors errors}, and
* {@link #getWarnings warnings}.
*/
protected void doUnload() {
doUnload(null, true);
}
/**
* @author Phong Nguyen Le - Jul 17, 2006
* @since 1.0
*/
private final class ContentTreeIterator extends AbstractTreeIterator {
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = 1L;
/**
* @param object
*/
private ContentTreeIterator(Object object) {
super(object);
}
protected Iterator getChildren(Object object) {
if (object instanceof EObject) {
ArrayList children = new ArrayList();
EContentsEList contents = new EContentsEList((EObject) object) {
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.util.EContentsEList#resolve()
*/
protected boolean resolve() {
return false;
}
};
for (Iterator iter = contents.basicIterator(); iter.hasNext();) {
EObject o = (EObject) iter.next();
if (o.eResource() == MultiFileXMIResourceImpl.this
|| o.eIsProxy()) {
children.add(o);
}
}
return children.iterator();
}
return Collections.EMPTY_LIST.iterator();
}
}
/**
* Unloads this resource. Old objects will be come proxies and will be added
* to the specified collection <code>proxies</code>
*
* @param proxies
* @param remove
* if <code>true</code> will remove all the unloaded objects in
* the resource from their containers and all opposite feature
* data of the unloaded objects will be cleared.
*/
protected void doUnload(Collection proxies, boolean remove) {
isUnloading = true;
try {
// from ResourceImpl
//
Iterator allContents = getAllProperContents(new ArrayList(
getContents()));
// This guard is needed to ensure that clear doesn't make the
// resource
// become loaded.
//
if (!getContents().isEmpty()) {
if (remove) {
getContents().clear();
} else {
// don't call getContents().clear() to keep the references
// to elements
// that just became proxies after unload
//
contents = null;
}
}
getErrors().clear();
getWarnings().clear();
ArrayList<EObject> unloadedObjects = new ArrayList<EObject>();
ArrayList allContentList = new ArrayList();
while (allContents.hasNext()) {
allContentList.add(allContents.next());
}
Iterator it = allContentList.iterator();
try {
while (it.hasNext()) {
try {
InternalEObject o = (InternalEObject) it
.next();
unloaded(o, remove);
unloadedObjects.add(o);
} catch (Exception e) {
CommonPlugin.INSTANCE.log(e);
}
}
} catch (Exception e) {
CommonPlugin.INSTANCE.log(e);
}
if (proxies != null && !unloadedObjects.isEmpty()) {
proxies.addAll(unloadedObjects);
}
if (remove) {
// remove the unloaded objects from its container to prevent the
// whole library from staying
// in memory if only one of its element is leaked
//
for (Iterator iter = unloadedObjects.iterator(); iter.hasNext();) {
EObject object = (EObject) iter.next();
EcoreUtil.remove(object);
}
}
// from XMLResourceIml
//
if (idToEObjectMap != null) {
for (Iterator iter = idToEObjectMap.keySet().iterator(); iter
.hasNext();) {
((MultiFileResourceSetImpl) getResourceSet())
.getGuidToMethodElementMap().remove(iter.next());
}
idToEObjectMap.clear();
}
if (eObjectToIDMap != null) {
eObjectToIDMap.clear();
}
if (eObjectToExtensionMap != null) {
eObjectToExtensionMap.clear();
}
if (intrinsicIDToEObjectMap != null) {
intrinsicIDToEObjectMap.clear();
}
modificationStamp = IResource.NULL_STAMP;
} finally {
isUnloading = false;
}
}
protected void unloaded(InternalEObject internalEObject) {
unloaded(internalEObject, true);
}
/**
* @param internalEObject
* @param clear
* if <code>true</code> all opposite feature data of the
* unloaded objects will be cleared.
*/
private void unloaded(InternalEObject internalEObject, boolean clear) {
String guid = MultiFileSaveUtil.getGuid(internalEObject);
if (guid != null) {
URI uri = resourceDescriptor != null ? MultiFileURIConverter
.createURI(resourceDescriptor.getId()) : getURI();
internalEObject.eSetProxyURI(uri.appendFragment(guid));
}
internalEObject.eAdapters().clear();
if (internalEObject instanceof MultiResourceEObject && clear) {
MultiResourceEObject multiResourceEObject = ((MultiResourceEObject) internalEObject);
// clear own opposite feature map
//
Map oppositeFeatureMap = multiResourceEObject
.basicGetOppositeFeatureMap();
if (oppositeFeatureMap != null) {
oppositeFeatureMap.clear();
}
// remove itself from all opposite features
//
multiResourceEObject.removeFromAllOppositeFeatures();
}
if(internalEObject instanceof ContentDescription || internalEObject instanceof Section) {
// set all string attributes to NULL to release memory
//
for (EAttribute attr : internalEObject.eClass().getEAllAttributes()) {
if(attr != UmaPackage.eINSTANCE.getMethodElement_Guid() &&
attr.getEAttributeType().getInstanceClass().isAssignableFrom(String.class)) {
internalEObject.eSet(attr, attr.getDefaultValue());
}
}
if(internalEObject.eDirectResource() != null && internalEObject instanceof MultiResourceEObject) {
((MultiResourceEObject)internalEObject).eSetResource(null);
}
}
}
public void detachedAll(EObject eObj) {
if (useIDs()) {
detachedAllWithIDs(eObj);
} else {
basicDetachedAll(eObj);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.resource.Resource.Internal#detached(org.eclipse.emf.ecore.EObject)
*/
public void detached(EObject eObject) {
detachedAll(eObject);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.resource.impl.ResourceImpl#createModificationTrackingAdapter()
*/
protected Adapter createModificationTrackingAdapter() {
return new ModificationTrackingAdapter() {
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.resource.impl.ResourceImpl.ModificationTrackingAdapter#notifyChanged(org.eclipse.emf.common.notify.Notification)
*/
public void notifyChanged(Notification notification) {
// don't handle OppositeFeatureNotification b/c it does not
// really modify this resource
//
if (notification instanceof OppositeFeatureNotification) {
return;
}
super.notifyChanged(notification);
}
};
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.resource.impl.ResourceImpl#setModified(boolean)
*/
public void setModified(boolean isModified) {
// boolean wasModified = isModified();
super.setModified(isModified);
// if(MultiFileSaveUtil.getMethodElement(this) instanceof
// ProcessComponent) {
// System.out.println("MultiFileXMIResourceImpl.setModified(): " +
// this);
// }
// this code is needed to set dirty flag to the item provider's label
//
// if(wasModified != isModified && !getContents().isEmpty()) {
// // refresh the label of the resource's object
// //
// EObject obj = (EObject) getContents().get(0);
// for (Iterator iter = obj.eAdapters().iterator(); iter.hasNext();) {
// Object adapter = iter.next();
// if(adapter instanceof ItemProviderAdapter) {
// ((ItemProviderAdapter)adapter).fireNotifyChanged(new
// ViewerNotification(new NotificationImpl(Notification.SET, obj, obj),
// obj, false, true));
// }
// }
// }
if (MultiFileSaveUtil.DEBUG) {
if (testResourceLoaded
&& getURI().toString().equals(testResourceURIStr)) {
System.out.println("isModified=" + isModified); //$NON-NLS-1$
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.common.notify.impl.NotifierImpl#eDeliver()
*/
public boolean eDeliver() {
ResourceSet resourceSet = getResourceSet();
if (resourceSet != null && !resourceSet.eDeliver())
return false;
return super.eDeliver();
}
public void save(Map options) throws IOException {
boolean old = DefaultValueManager.INSTANCE.isUseStatic();
try {
DefaultValueManager.INSTANCE.setUseStatic(true);
if (options == null) {
options = MultiFileResourceSetImpl.DEFAULT_SAVE_OPTIONS;
}
super.save(options);
// Special handling for saving MethodLibrary to remove all references to
// MethodConfigurations from library file.
//
MethodElement e = PersistenceUtil.getMethodElement(this);
if (e instanceof MethodLibrary) {
MethodLibrary lib = (MethodLibrary) e;
// remove ResourceDescriptors of configuration files
//
ResourceManager resMgr = MultiFileSaveUtil.getResourceManager(this);
if (resMgr != null) {
for (Iterator iter = lib.getPredefinedConfigurations()
.iterator(); iter.hasNext();) {
MethodConfiguration config = (MethodConfiguration) iter
.next();
ResourceDescriptor resDesc = resMgr
.getResourceDescriptor(config.getGuid());
if (resDesc != null) {
EcoreUtil.remove(resDesc);
}
}
}
List configs = new ArrayList(lib.getPredefinedConfigurations());
boolean oldDeliver = lib.eDeliver();
try {
lib.eSetDeliver(false);
lib.getPredefinedConfigurations().clear();
// Save library file again to remove all references to configurations.
// The previous save is still needed to save new configuration in its own file
//
super.save(options);
} finally {
lib.getPredefinedConfigurations().addAll(configs);
lib.eSetDeliver(oldDeliver);
}
}
}
finally {
DefaultValueManager.INSTANCE.setUseStatic(old);
}
}
public URI getFinalURI() {
if (finalURI != null) {
return finalURI;
}
return getURI();
}
public void setFinalURI(URI uri) {
finalURI = uri;
}
public void backUpURI() {
oldURI = getURI();
}
public boolean hasTempURI() {
if (currentTxID != null) {
return createTempURI().equals(getURI());
}
return false;
}
private URI createTempURI() {
MethodElement e = PersistenceUtil.getMethodElement(this);
return URI.createFileURI(new StringBuffer(getTempDir()).append(
File.separator).append(currentTxID)
.append("new").append(e.getGuid()).toString()); //$NON-NLS-1$
}
static String getTempDir() {
if (tempDir == null) {
tempDir = new File(FileManager.getTempDir(), "EPF").getAbsolutePath(); //$NON-NLS-1$
}
return tempDir;
}
/**
* Sets the temporary URI to save this resource to and it will be renamed to
* the original URI when saving is done
*/
public void setTempURI(String txID) {
if (finalURI == null) {
finalURI = oldURI = getURI();
currentTxID = txID;
URI tempURI = createTempURI();
setURI(tempURI);
MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) getResourceSet();
resourceSet.getURIToTempURIMap().put(oldURI, tempURI);
}
}
/**
* 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) {
setURI(oldURI);
}
}
public boolean txStarted() {
return moveStarted() || saveStarted();
}
protected void updateTimeStamps() {
FileManager.getInstance().refresh(this);
lastLoadTimeStamp = System.currentTimeMillis();
IFileInfo info = getFileInfo();
if(info != null) {
modificationStamp = info.getModificationStamp();
}
}
/**
* Checks if this resource is currently synchronized with its data store
*
* @return <li> -1 don't know
* <li> 0 no
* <li> 1 yes
* @deprecated use {@link #isSynchronized()} instead
*/
public int checkSynchronized() {
// long currentTime = new File(getURI().toFileString()).lastModified();
// if(MultiFileSaveUtil.same(currentTime, fileLastModified)) {
// // some team providers changed the timestamp of last file modification by removing second fraction
// // even the file was not changed
// //
// return 1;
// }
// return -1;
return isSynchronized() ? 1 : 0;
}
public boolean isSynchronized() {
IFileInfo fileInfo = getFileInfo();
if (fileInfo != null) {
return modificationStamp == fileInfo.getModificationStamp();
}
else {
return true;
}
}
public void txFinished(boolean successful) {
boolean wasMove = !oldURI.equals(finalURI);
if (successful) {
setURI(finalURI);
if(!wasMove) {
setModified(false);
}
updateTimeStamps();
if(!wasMove) {
MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) getResourceSet();
if(resourceSet != null) {
resourceSet.getUnresolvedProxyMarkerManager().validateMarkers(this);
}
}
} else {
restoreURI();
if (wasMove) {
// finalURI must be cleared before restoring URI of its child
// resources so the URI of its child resources can be resolved
// correctly. See ResourceDescriptorImpl.getResolvedURI()
//
finalURI = null;
// restore uri of ResourceDescriptor of this resource
//
MultiFileSaveUtil.updateURIMappings(this, oldURI, null, true);
}
}
if (oldURI != null) {
MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) getResourceSet();
if (resourceSet != null) {
resourceSet.getURIToTempURIMap().remove(oldURI);
}
oldURI = null;
}
currentTxID = null;
finalURI = null;
}
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 restore() {
File src = null, dest = null;
boolean moved = false;
if (backupFile != null) {
src = new File(backupFile);
dest = new File(getFinalURI().toFileString());
} else {
moved = oldURI != null && !oldURI.equals(finalURI);
if (moved) {
File file = new File(getFinalURI().toFileString());
dest = new File(oldURI.toFileString());
moved = file.exists() && !dest.exists();
if (moved) {
src = file;
}
}
}
if (src != null) {
if (dest.exists()) {
FileUtil.moveFile(dest,new File(getURI().toFileString()));
}
boolean success;
if (moved) {
success = MultiFileSaveUtil.move(this, src, dest);
// if(success) {
// MultiFileSaveUtil.updateURIMappings(this, null);
// }
} else {
// don't restore file if the source and destination are the same
//
success = src.lastModified() == dest.lastModified() && FileUtil.getSize(src) == FileUtil.getSize(dest);
if(!success) {
success = FileUtil.moveFile(src, dest);
}
}
if (!success) {
throw new MultiFileIOException(NLS.bind(PersistenceResources.restoreResourceError_msg,
FileManager.toFileString(getFinalURI())));
}
return true;
}
return false;
}
URI getOldURI() {
return oldURI;
}
boolean moveStarted() {
return oldURI != null && !oldURI.equals(getFinalURI());
}
boolean saveStarted() {
return currentTxID != null;
}
private void refreshURIOfChildResources() {
// refresh resolve URIs in ResourceDescriptors of the child
// resources of this resource
//
HashMap<URI, ResourceDescriptor> oldURIToResourceDescriptorMap = null;
ResourceManager resMgr = MultiFileSaveUtil
.getResourceManager(this);
if (resMgr != null) {
oldURIToResourceDescriptorMap = new HashMap<URI, ResourceDescriptor>();
for (Iterator<?> iter = resMgr.eAllContents(); iter
.hasNext();) {
Object obj = iter.next();
if (obj instanceof ResourceDescriptor) {
ResourceDescriptor desc = ((ResourceDescriptor) obj);
oldURIToResourceDescriptorMap.put(desc
.getResolvedURI(), desc);
desc.clearResolvedURI();
}
}
}
// refresh URI of loaded child resources of this resource
//
if (oldURIToResourceDescriptorMap != null) {
// go thru the list of loaded resources in resource set
// to update the URI
//
for (Resource res : getResourceSet().getResources()) {
ResourceDescriptor desc = (ResourceDescriptor) oldURIToResourceDescriptorMap
.get(res.getURI());
if (desc != null) {
res.setURI(desc.getResolvedURI());
}
}
}
}
public void commit() {
if (finalURI != null && !getContents().isEmpty()) {
File finalFile = new File(finalURI.toFileString());
boolean wasMove = !oldURI.equals(finalURI);
if (wasMove) {
Object e = PersistenceUtil.getMethodElement(this);
if (e instanceof ContentDescription) {
if (finalFile.exists()) {
// name for finalFile is already taken
// try to get the next available name
//
finalURI = URI.createFileURI(MethodLibraryPersister
.getNextAvailableFileName(finalFile.getParent()
+ File.separator,
(ContentDescription) e));
finalFile = new File(finalURI.toFileString());
}
}
} 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 ? oldURI.toFileString()
: getURI().toFileString());
boolean success = false;
Exception ex = null;
if (wasMove) {
success = MultiFileSaveUtil.move(this, currentFile, finalFile);
} else {
// some CM provider like ClearCase renamed the versioned file in
// 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
//
try {
FileUtil.doMoveFile(currentFile, finalFile);
success = true;
}
catch(Exception e) {
ex = e;
}
}
if (!success) {
String msg = NLS.bind(PersistenceResources.renameError_msg,
currentFile, finalFile);
if(ex != null) {
msg = msg + ": " + (ex.getMessage() != null ? ex.getMessage() : ex.toString()); //$NON-NLS-1$
}
throw new MultiFileIOException(msg);
} else {
if (wasMove) {
// refresh resolve URI of ResourceDescriptor of this
// resource
//
ResourceDescriptor resDesc = MultiFileSaveUtil
.getResourceDescriptor(this);
if (resDesc != null) {
resDesc.clearResolvedURI();
resDesc.getResolvedURI();
}
else {
if (MultiFileSaveUtil.DEBUG) {
MethodElement e = PersistenceUtil
.getMethodElement(this);
if (e != null
&& !getLibraryPersister()
.hasOwnResourceWithoutReferrer(e)) {
String msg = "FATAL ERROR: no ResourceDescriptor found in parent resource for " + this; //$NON-NLS-1$
CommonPlugin.INSTANCE.log(msg);
System.err.println(msg);
}
}
}
refreshURIOfChildResources();
}
RefreshJob.getInstance().resourceSaved(this);
}
}
}
public String getBackupFilePath() {
String backupFile = new StringBuffer(getTempDir())
.append(File.separator)
.append(currentTxID)
.append("old").append(PersistenceUtil.getMethodElement(this).getGuid()).toString(); //$NON-NLS-1$
return backupFile;
}
/**
* @return the lastLoadTimeStamp
*/
public long getLastLoadTimeStamp() {
return lastLoadTimeStamp;
}
static void clearDetachedEObjectToIDMap() {
DETACHED_EOBJECT_TO_ID_MAP.clear();
}
/**
* @param resDesc
*/
void setResourceDescriptor(ResourceDescriptor resDesc) {
resourceDescriptor = resDesc;
}
public ResourceDescriptor getResourceDescriptor() {
return resourceDescriptor;
}
/* (non-Javadoc)
* @see org.eclipse.epf.library.persistence.ILibraryResource#getLoadStamp()
*/
public long getLoadStamp() {
return getLastLoadTimeStamp();
}
public URI getProxyURI(EObject object) {
String guid = MultiFileSaveUtil.getGuid(object);
if (guid != null) {
ResourceDescriptor resourceDescriptor = this.resourceDescriptor != null ? this.resourceDescriptor :
MultiFileSaveUtil.getResourceDescriptor(this);
URI uri = resourceDescriptor != null ? MultiFileURIConverter
.createURI(resourceDescriptor.getId()) : getURI();
return uri.appendFragment(guid);
}
return getURI().appendFragment(getID(object));
}
public void setTxID(String txID) {
setTempURI(txID);
}
private ILibraryPersister getLibraryPersister() {
return ((MultiFileResourceSetImpl)resourceSet).getPersister();
}
}