001/* 002 * (C) Copyright 2006-2008 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * "Stephane Lacoin (aka matic) <slacoin@nuxeo.org>" 016 */ 017package org.nuxeo.ecm.core.persistence; 018 019import javax.persistence.EntityManager; 020import javax.persistence.EntityManagerFactory; 021import javax.persistence.EntityTransaction; 022import javax.persistence.TransactionRequiredException; 023 024import org.apache.commons.logging.Log; 025import org.apache.commons.logging.LogFactory; 026 027/** 028 * @author "Stephane Lacoin (aka matic) <slacoin@nuxeo.org>" 029 */ 030public class PersistenceProvider { 031 032 protected static final Log log = LogFactory.getLog(PersistenceProvider.class); 033 034 protected EntityManagerFactory emf; 035 036 protected final EntityManagerFactoryProvider emfProvider; 037 038 public PersistenceProvider(EntityManagerFactoryProvider emfProvider) { 039 this.emfProvider = emfProvider; 040 } 041 042 public void openPersistenceUnit() { 043 if (emfProvider == null) { 044 throw new IllegalArgumentException("emfProvider not set"); 045 } 046 if (emf == null) { 047 synchronized (PersistenceProvider.class) { 048 if (emf == null) { 049 emf = emfProvider.getFactory(); 050 } 051 } 052 } 053 } 054 055 public void closePersistenceUnit() { 056 if (emf == null) { 057 return; 058 } 059 if (emf.isOpen()) { 060 emf.close(); 061 } 062 emf = null; 063 } 064 065 protected EntityManager doAcquireEntityManager() { 066 if (emf == null) { 067 openPersistenceUnit(); 068 } 069 return emf.createEntityManager(); 070 } 071 072 protected EntityTransaction getTransaction(EntityManager em) { 073 try { 074 return em.getTransaction(); 075 } catch (IllegalStateException e) { 076 return null; // JTA container, no manual access to transaction 077 } 078 } 079 080 public EntityManager acquireEntityManager() { 081 return doAcquireEntityManager(); 082 } 083 084 public EntityManager acquireEntityManagerWithActiveTransaction() { 085 EntityManager em = doAcquireEntityManager(); 086 doBegin(em); 087 return em; 088 } 089 090 protected void doBegin(EntityManager em) { 091 EntityTransaction et = getTransaction(em); 092 if (et != null) { 093 et.begin(); 094 } 095 } 096 097 protected void doCommit(EntityManager em) { 098 try { 099 em.flush(); 100 } catch (TransactionRequiredException e) { 101 // ignore 102 } 103 EntityTransaction et = getTransaction(em); 104 if (et == null || !et.isActive()) { 105 return; 106 } 107 et.commit(); 108 } 109 110 protected void doRollback(EntityManager em) { 111 try { 112 em.flush(); 113 } catch (TransactionRequiredException e) { 114 // ignore 115 } 116 EntityTransaction et = getTransaction(em); 117 if (et == null || !et.isActive()) { 118 return; 119 } 120 et.rollback(); 121 } 122 123 protected void releaseEntityManager(EntityManager em) { 124 if (!em.isOpen()) { 125 return; 126 } 127 try { 128 doCommit(em); 129 } finally { 130 if (em.isOpen()) { 131 em.clear(); 132 em.close(); 133 } 134 } 135 } 136 137 public void releaseEntityManagerWithRollback(EntityManager em) { 138 if (!em.isOpen()) { 139 return; 140 } 141 try { 142 doRollback(em); 143 } finally { 144 if (em.isOpen()) { 145 em.clear(); 146 em.close(); 147 } 148 } 149 } 150 151 public interface RunCallback<T> { 152 T runWith(EntityManager em); 153 } 154 155 public <T> T run(Boolean needActiveSession, RunCallback<T> callback) { 156 // needActiveSession now unused 157 Thread myThread = Thread.currentThread(); 158 ClassLoader lastLoader = myThread.getContextClassLoader(); 159 myThread.setContextClassLoader(getClass().getClassLoader()); 160 try { // insure context class loader restoring 161 EntityManager em = doAcquireEntityManager(); 162 doBegin(em); 163 try { // insure entity manager releasing 164 return callback.runWith(em); 165 } finally { 166 releaseEntityManager(em); 167 } 168 } finally { 169 myThread.setContextClassLoader(lastLoader); 170 } 171 } 172 173 public interface RunVoid { 174 void runWith(EntityManager em); 175 } 176 177 public void run(Boolean needActiveSession, RunVoid callback) { 178 // needActiveSession now unused 179 Thread myThread = Thread.currentThread(); 180 ClassLoader lastLoader = myThread.getContextClassLoader(); 181 myThread.setContextClassLoader(getClass().getClassLoader()); 182 try { // insure context class loader restoring 183 EntityManager em = doAcquireEntityManager(); 184 doBegin(em); 185 try { // insure entity manager releasing 186 callback.runWith(em); 187 } finally { 188 releaseEntityManager(em); 189 } 190 } finally { 191 myThread.setContextClassLoader(lastLoader); 192 } 193 } 194 195}