/******************************************************************************* * Copyright (C) 2011, Robin Stocker <robin@nibor.org> * * 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 *******************************************************************************/ package org.eclipse.egit.ui.internal.revision; import java.io.ByteArrayInputStream; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.egit.core.internal.CompareCoreUtils; import org.eclipse.egit.ui.Activator; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.team.core.history.IFileRevision; /** * Editable revision backed by an {@link IFile}. * <p> * Use {@link LocationEditableRevision} if you just have a path (for * non-workspace files). */ public class ResourceEditableRevision extends EditableRevision { private final IFile file; private final IRunnableContext runnableContext; /** * Create a new FileEditableRevision. * * @param fileRevision * @param file * the file to write the changed contents to * @param runnableContext * the context to use for the file write operation */ public ResourceEditableRevision(IFileRevision fileRevision, IFile file, IRunnableContext runnableContext) { super(fileRevision, CompareCoreUtils.getResourceEncoding(file)); this.file = file; Assert.isNotNull(runnableContext); this.runnableContext = runnableContext; } @Override public void setContent(final byte[] newContent) { try { // Don't fork: if we are called from a thread which locked // workspace our *forked* operation will never complete because it // requires file lock which cannot be acquired from another thread ISchedulingRule rule = Job.getJobManager().currentRule(); boolean fork = true; if (rule instanceof IResource) { if (file.exists() && ((IResource) rule).isConflicting(file)) fork = false; } runnableContext.run(fork, false, new IRunnableWithProgress() { @Override public void run(IProgressMonitor myMonitor) throws InvocationTargetException, InterruptedException { try { file.setContents(new ByteArrayInputStream(newContent), false, true, myMonitor); } catch (CoreException e) { throw new InvocationTargetException(e); } } }); } catch (InvocationTargetException e) { Activator.handleError(e.getTargetException().getMessage(), e.getTargetException(), true); } catch (InterruptedException e) { // ignore here } } /** * @return the resource of this revision */ public IFile getFile() { return file; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((file == null) ? 0 : file.hashCode()); result = prime * result + ((runnableContext == null) ? 0 : runnableContext.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; ResourceEditableRevision other = (ResourceEditableRevision) obj; if (file == null) { if (other.file != null) return false; } else if (!file.equals(other.file)) return false; if (runnableContext == null) { if (other.runnableContext != null) return false; } else if (!runnableContext.equals(other.runnableContext)) return false; return true; } }