/*******************************************************************************
* Copyright (c) 2004, 2010 BREDEX GmbH.
* 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:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.client.core.persistence;
import java.sql.SQLException;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.LockTimeoutException;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import javax.persistence.PessimisticLockException;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jubula.client.core.businessprocess.progress.OperationCanceledUtil;
import org.eclipse.jubula.client.core.i18n.Messages;
import org.eclipse.jubula.client.core.model.IPersistentObject;
import org.eclipse.jubula.tools.internal.constants.StringConstants;
import org.eclipse.jubula.tools.internal.exception.ProjectDeletedException;
import org.eclipse.jubula.tools.internal.messagehandling.MessageIDs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* base persistence manager class
* @author BREDEX GmbH
* @created 07.09.2004
*/
public abstract class PersistenceManager {
/** the logger */
private static Logger log =
LoggerFactory.getLogger(PersistenceManager.class);
/**
*
*/
protected PersistenceManager() {
log.debug("deprecated"); //$NON-NLS-1$
}
/**
* @param obj obj to handle the PersistenceException for
* @param e thrown exception
* @throws PMException in case of general db error
* @throws PMDirtyVersionException in case of version conflict
* @throws PMAlreadyLockedException in case of locked obj
* @throws OperationCanceledException in case of canceled operation
*/
private static void handleDetailedPersistenceException(
IPersistentObject obj,
PersistenceException e) throws PMException, PMDirtyVersionException,
PMAlreadyLockedException, OperationCanceledException {
OperationCanceledUtil.checkForOperationCanceled(e);
String msg = null;
String objName = null;
if (obj == null) {
objName = Messages.UnknownObject;
} else {
objName = obj.getName();
}
// please attend the order of instance of verifications
Throwable rootCause = ExceptionUtils.getRootCause(e);
if (e instanceof EntityNotFoundException) {
msg = objName + StringConstants.SPACE
+ Messages.WasDeletedByAnotherTransaction + StringConstants.DOT;
log.debug(msg, e);
throw new PMObjectDeletedException(obj, msg,
MessageIDs.E_DELETED_OBJECT);
} else if (e instanceof OptimisticLockException) {
msg = objName + StringConstants.SPACE
+ Messages.WasModifiedInDBDirtyVersion + StringConstants.DOT;
log.debug(msg, e);
throw new PMDirtyVersionException(obj, msg,
MessageIDs.E_STALE_OBJECT);
} else if (isLockException(e)) {
msg = objName + StringConstants.SPACE
+ Messages.AlreadyLockedCurrentlyLockAttemptFailed
+ StringConstants.DOT;
log.debug(msg, e);
throw new PMAlreadyLockedException(obj, msg,
MessageIDs.E_OBJECT_IN_USE);
} else if (rootCause instanceof SQLException) {
SQLException sqlException = (SQLException)rootCause;
msg = sqlException.getMessage();
log.debug(msg, e);
throw new PMException(msg, MessageIDs.E_SQL_EXCEPTION);
}
msg = Messages.GeneralDatabaseErrorFor + StringConstants.SPACE
+ objName + StringConstants.DOT;
log.error(msg, e);
throw new PMException(msg, MessageIDs.E_DATABASE_GENERAL);
}
/**
* check if the exception is caused by a failed lock attempt
* @param e Persistence (JPA / EclipseLink) exception
* @return true if e is caused by a failed lock attempt
*/
private static boolean isLockException(PersistenceException e) {
for (Throwable cause : ExceptionUtils.getThrowables(e)) {
if (cause instanceof PessimisticLockException
|| cause instanceof OptimisticLockException
|| cause instanceof LockTimeoutException) {
return true;
} else if (cause instanceof SQLException) {
if (((SQLException)cause).getSQLState() != null
&& ((SQLException)cause).getSQLState().startsWith("61000")) { //$NON-NLS-1$ // NOPMD by al on 3/19/07 1:38 PM
// error state in Oracle
return true;
}
}
}
return false;
}
/**
* @param obj obj caused exception
* @param e Persistence (JPA / EclipseLink) exception
* @param editSupp associated editSupport for editor
* @throws PMException in case of any db error
*/
public static void handleDBExceptionForEditor(IPersistentObject obj,
PersistenceException e, EditSupport editSupp) throws PMException {
if (isLockException(e)) {
editSupp.reinitializeEditSupport();
} else if (e instanceof EntityNotFoundException) {
editSupp.close();
} else {
editSupp.reloadEditSession();
}
handleDetailedPersistenceException(obj, e);
}
/**
* @param obj
* obj to handle the PersistenceException for hint: obj could be
* null (for example for a db commit, where the causing object is
* unknown
* @param e
* thrown exception
* @throws PMAlreadyLockedException
* in case of locked obj
* @throws PMDirtyVersionException
* in case of version conflict
* @throws PMException
* in case of general db error
* @throws ProjectDeletedException
* if the project was deleted in another instance
*/
public static void handleDBExceptionForMasterSession(IPersistentObject obj,
PersistenceException e)
throws PMAlreadyLockedException, PMDirtyVersionException, PMException,
ProjectDeletedException {
final GeneralStorage gs = GeneralStorage.getInstance();
if (isLockException(e)) {
gs.recoverSession();
} else {
gs.reloadMasterSession(new NullProgressMonitor());
}
handleDetailedPersistenceException(obj, e);
}
/**
* handles DBExceptions for any session
* @param obj obj caused exception
* @param e Persistence (JPA / EclipseLink) exception
* @param s associated session
* @throws PMException in case of any db error
*/
public static void handleDBExceptionForAnySession(IPersistentObject obj,
PersistenceException e, EntityManager s) throws PMException {
Persistor.instance().dropSession(s);
handleDetailedPersistenceException(obj, e);
}
}