blob: 1af60d4b4de32421b9b6e0e07443176f45cebf4f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012-2013 EclipseSource Muenchen GmbH 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:
* Edgar Mueller
******************************************************************************/
package org.eclipse.emf.emfstore.internal.client.model.util;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.emfstore.client.ESLocalProject;
import org.eclipse.emf.emfstore.client.handler.ESChecksumErrorHandler;
import org.eclipse.emf.emfstore.internal.client.common.UnknownEMFStoreWorkloadCommand;
import org.eclipse.emf.emfstore.internal.client.model.Activator;
import org.eclipse.emf.emfstore.internal.client.model.ESWorkspaceProviderImpl;
import org.eclipse.emf.emfstore.internal.client.model.ProjectSpace;
import org.eclipse.emf.emfstore.internal.client.model.impl.api.ESLocalProjectImpl;
import org.eclipse.emf.emfstore.internal.common.model.Project;
import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.internal.common.model.util.SerializationException;
import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESGlobalProjectIdImpl;
import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESSessionIdImpl;
import org.eclipse.emf.emfstore.internal.server.model.impl.api.versionspec.ESVersionSpecImpl;
import org.eclipse.emf.emfstore.internal.server.model.versioning.VersionSpec;
import org.eclipse.emf.emfstore.server.exceptions.ESException;
import org.eclipse.emf.emfstore.server.model.versionspec.ESPrimaryVersionSpec;
/**
* Pre-defined error handlers.
*
* @author emueller
* @author Lucas Koehler
*
*/
public enum ChecksumErrorHandler implements ESChecksumErrorHandler {
/**
* Logs the checksum comparison failure and continues execution of the caller.
*/
LOG {
/**
* {@inheritDoc}
*/
public boolean execute(ESLocalProject project, ESPrimaryVersionSpec versionSpec, IProgressMonitor monitor)
throws ESException {
WorkspaceUtil.logWarning(Messages.ChecksumErrorHandler_ChecksumComparisionFailed, null);
return true;
}
},
/**
* Logs the checksum comparison failure detailed: the serialization of both project spaces is written in seperate
* files. The execution of the caller will then be continued.
*/
LOG_DETAILED {
/**
* {@inheritDoc}
*/
public boolean execute(ESLocalProject localProject, ESPrimaryVersionSpec versionSpec, IProgressMonitor monitor)
throws ESException {
return LogDetailed.execute(localProject, versionSpec, monitor, false);
}
},
/**
* Logs the checksum comparison failure detailed: the serialization of both project spaces is written in seperate
* files. The execution of the caller will then be discontinued.
*/
LOG_DETAILED_AND_CANCEL
{
/**
* {@inheritDoc}
*/
public boolean execute(ESLocalProject localProject, ESPrimaryVersionSpec versionSpec, IProgressMonitor monitor)
throws ESException {
return LogDetailed.execute(localProject, versionSpec, monitor, true);
}
},
/**
* Aborts execution of the caller.
*/
CANCEL {
/**
* {@inheritDoc}
*/
public boolean execute(ESLocalProject project, ESPrimaryVersionSpec versionSpec, IProgressMonitor monitor)
throws ESException {
return false;
}
},
/**
* Fixes the checksum comparison failure by deleting the {@link ProjectSpace} that got
* in an inconsistent state and checking it out again.<br>
* <b>Note</b>: all references to the project space that will be deleted should to be taken care of.
*/
AUTOCORRECT {
/**
* {@inheritDoc}
*/
public boolean execute(final ESLocalProject project, final ESPrimaryVersionSpec versionSpec,
IProgressMonitor monitor) throws ESException {
final ESLocalProjectImpl localProjectImpl = (ESLocalProjectImpl) project;
final ProjectSpace projectSpace = localProjectImpl.toInternalAPI();
final Resource projectResource = localProjectImpl.toInternalAPI().getProject().eResource();
final Project fetchedProject = new UnknownEMFStoreWorkloadCommand<Project>(monitor) {
@Override
public Project run(IProgressMonitor monitor) throws ESException {
final ESSessionIdImpl sessionIdImpl = (ESSessionIdImpl) project.getUsersession().getSessionId();
final ESGlobalProjectIdImpl globalProjectIdImpl = (ESGlobalProjectIdImpl) project.getRemoteProject()
.getGlobalProjectId();
final ESVersionSpecImpl<?, ? extends VersionSpec> versionSpecImpl = (ESVersionSpecImpl<?, ?>) versionSpec;
return ESWorkspaceProviderImpl.getInstance().getConnectionManager().getProject(
sessionIdImpl.toInternalAPI(), globalProjectIdImpl.toInternalAPI(),
ModelUtil.clone(versionSpecImpl.toInternalAPI()));
}
}.execute();
if (fetchedProject == null) {
throw new ESException(Messages.ChecksumErrorHandler_ServerReturnedNullProject);
}
projectResource.getContents().clear();
projectResource.getContents().add(fetchedProject);
try {
projectResource.save(ModelUtil.getResourceSaveOptions());
} catch (final IOException ex) {
throw new ESException(Messages.ChecksumErrorHandler_SaveFailedWhileAutocorrect);
}
projectSpace.setProject(fetchedProject);
projectSpace.init();
return true;
}
}
}
/**
* Logs the checksum comparison failure detailed: the serialization of both project spaces is written in separate
* files.
*/
final class LogDetailed {
private LogDetailed() {
// private ctor
}
/**
* Execute the detailed comparison.
*
* @param localProject the {@link ESLocalProject} whose contents should be checked
* @param versionSpec the version for which the comparison should be checked
* @param monitor a {@link IProgressMonitor} instance
* @param shouldFail whether to continue with in case the comparison failed
* @return the inverse of {@code shouldFail} meaning that we indicate an error occurred
* in case the comparison failed
*
* @throws ESException in case the comparison fails for technical reasons
*/
public static boolean execute(ESLocalProject localProject, ESPrimaryVersionSpec versionSpec,
IProgressMonitor monitor, boolean shouldFail) throws ESException {
WorkspaceUtil.logWarning("Checksum comparison failed.", null); //$NON-NLS-1$
final Project project = ESLocalProjectImpl.class.cast(localProject).toInternalAPI().getProject();
final ESLocalProject serverESProject = localProject
.getRemoteProject()
.checkout(
"log_error_checksum_debug_checkout", localProject.getUsersession(), versionSpec, //$NON-NLS-1$
new NullProgressMonitor());
final Project serverProject = ESLocalProjectImpl.class.cast(serverESProject).toInternalAPI()
.getProject();
try {
final Map<Object, Object> formatOptions = new LinkedHashMap<Object, Object>();
formatOptions.put(XMLResource.OPTION_DECLARE_XML, Boolean.TRUE);
formatOptions.put(XMLResource.OPTION_FORMATTED, Boolean.TRUE);
final String localSerialization = ModelUtil
.eObjectToString(project, ModelUtil.getResourceSaveOptions());
final String serverSerialization = ModelUtil.eObjectToString(serverProject,
ModelUtil.getResourceSaveOptions());
serverESProject.delete(new NullProgressMonitor());
final File localFile = Activator.getDefault().getBundle().getDataFile("localProjectSerialization.txt"); //$NON-NLS-1$
final File serverFile = Activator.getDefault().getBundle()
.getDataFile("serverProjectSerialization.txt"); //$NON-NLS-1$
final FileWriter fileWriterLocal = new FileWriter(localFile);
fileWriterLocal.write(localSerialization);
fileWriterLocal.close();
final FileWriter fileWriterServer = new FileWriter(serverFile);
fileWriterServer.write(serverSerialization);
fileWriterServer.close();
} catch (final SerializationException ex) {
WorkspaceUtil.logException("Couldn't log the serializations.", ex); //$NON-NLS-1$
} catch (final IOException ex) {
WorkspaceUtil.logException("Couldn't save the serializations.", ex); //$NON-NLS-1$
}
return !shouldFail;
}
}