package uk.ac.ebi.fg.myequivalents.managers.impl.db; import javax.persistence.EntityManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.ac.ebi.fg.myequivalents.access_control.model.User; import uk.ac.ebi.fg.myequivalents.dao.access_control.UserDao; import uk.ac.ebi.fg.myequivalents.exceptions.SecurityException; import uk.ac.ebi.fg.myequivalents.managers.interfaces.MyEquivalentsManager; /** * <h2>An implementation of {@link MyEquivalentsManager} for the relational back end</h2> * * <p>This is a base class, which is extended by all the DB-based managers in this package.</p> * * <p>The relational database implementations of myEquivalents managers are run in a JVM which can connect to a JDBC-based * back end. This is further mediated by the object model in the core package, JPA/Hibernate mapping and DAO objects.</p> * * <p>Note that the DB-based managers instantiate a new {@link EntityManager Hibernate EntityManager} in their constructors. * This makes them one-entity-manager-per-request in many cases (e.g., when accessed by a web service). * This should be the best transactional model to use in such cases. You might decide a different approach, by keeping * an instance of this class for the time you wish. However, DB-based managers are not thread-safe, the idea is that * you instantiate a manager within one thread, do some operations from the same thread and then release the manager.</p> * * <p>The persistence-related invocations in this manager does the transaction management automatically * (i.e., they commit all implied changes upon operation invocation).</p> * * <dl><dt>date</dt><dd>Mar 18, 2013</dd></dl> * @author Marco Brandizi * */ public abstract class DbMyEquivalentsManager implements MyEquivalentsManager { protected final EntityManager entityManager; protected UserDao userDao; protected Logger log = LoggerFactory.getLogger ( this.getClass () ); /** * The default doesn't do any authentication, it's up to the subclasses to decide whether to login 'anonymous' * automatically or not. */ protected DbMyEquivalentsManager ( EntityManager entityManager ) { this ( entityManager, null, null ); } /** * This authenticates the user via {@link #setAuthenticationCredentials(String, String)}. */ public DbMyEquivalentsManager ( EntityManager entityManager, String email, String apiPassword ) { this.entityManager = entityManager; setAuthenticationCredentials ( email, apiPassword ); } /** * This performs user authentication, i.e., verifies the user credentials against the database and throws an exception * if they're invalid. That happens via {@link UserDao#login(String, String, boolean)}, which also means the anonymous * user is returned if email is null. */ protected User setAuthenticationCredentials ( String email, String password, boolean isUserPass ) throws SecurityException { this.userDao = new UserDao ( entityManager, email, password, isUserPass ); return this.userDao.getLoggedInUser (); } /** * Authenticates the user immediately, via {@link #setAuthenticationCredentials(String, String, boolean)}, using * the user API password (see documentation). The credentials are immediately verified against the database and a * {@link SecurityException} is thrown in case they aren't invalid. */ @Override public User setAuthenticationCredentials ( String email, String apiPassword ) throws SecurityException { return setAuthenticationCredentials ( email, apiPassword, false ); } /** * A facility internally useful */ protected String getUserEmail () { if ( this.userDao == null ) return null; User usr = this.userDao.getLoggedInUser (); return usr == null ? null : usr.getEmail (); } /** * Invokes {@link #userDao userDao.logOff()} and closes the {@link #entityManager}. */ @Override public void close () { userDao.logOff (); if ( entityManager.isOpen () ) entityManager.close (); } /** * Invokes {@link #close()}. */ @Override protected void finalize () throws Throwable { super.finalize (); this.close(); } }