001/* 002 * (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * "Stephane Lacoin (aka matic) <slacoin@nuxeo.org>" 018 */ 019package org.nuxeo.ecm.core.persistence; 020 021import javax.persistence.EntityManager; 022import javax.persistence.EntityManagerFactory; 023import javax.persistence.EntityTransaction; 024import javax.persistence.TransactionRequiredException; 025 026import org.apache.commons.logging.Log; 027import org.apache.commons.logging.LogFactory; 028 029/** 030 * @author "Stephane Lacoin (aka matic) <slacoin@nuxeo.org>" 031 */ 032public class PersistenceProvider { 033 034 protected static final Log log = LogFactory.getLog(PersistenceProvider.class); 035 036 protected EntityManagerFactory emf; 037 038 protected final EntityManagerFactoryProvider emfProvider; 039 040 public PersistenceProvider(EntityManagerFactoryProvider emfProvider) { 041 this.emfProvider = emfProvider; 042 } 043 044 public void openPersistenceUnit() { 045 if (emfProvider == null) { 046 throw new IllegalArgumentException("emfProvider not set"); 047 } 048 if (emf == null) { 049 synchronized (PersistenceProvider.class) { 050 if (emf == null) { 051 emf = emfProvider.getFactory(); 052 } 053 } 054 } 055 } 056 057 public void closePersistenceUnit() { 058 if (emf == null) { 059 return; 060 } 061 if (emf.isOpen()) { 062 emf.close(); 063 } 064 emf = null; 065 } 066 067 protected EntityManager doAcquireEntityManager() { 068 if (emf == null) { 069 openPersistenceUnit(); 070 } 071 return emf.createEntityManager(); 072 } 073 074 protected EntityTransaction getTransaction(EntityManager em) { 075 try { 076 return em.getTransaction(); 077 } catch (IllegalStateException e) { 078 return null; // JTA container, no manual access to transaction 079 } 080 } 081 082 public EntityManager acquireEntityManager() { 083 return doAcquireEntityManager(); 084 } 085 086 public EntityManager acquireEntityManagerWithActiveTransaction() { 087 EntityManager em = doAcquireEntityManager(); 088 doBegin(em); 089 return em; 090 } 091 092 protected void doBegin(EntityManager em) { 093 EntityTransaction et = getTransaction(em); 094 if (et != null) { 095 et.begin(); 096 } 097 } 098 099 protected void doCommit(EntityManager em) { 100 try { 101 em.flush(); 102 } catch (TransactionRequiredException e) { 103 // ignore 104 } 105 EntityTransaction et = getTransaction(em); 106 if (et == null || !et.isActive()) { 107 return; 108 } 109 et.commit(); 110 } 111 112 protected void doRollback(EntityManager em) { 113 try { 114 em.flush(); 115 } catch (TransactionRequiredException e) { 116 // ignore 117 } 118 EntityTransaction et = getTransaction(em); 119 if (et == null || !et.isActive()) { 120 return; 121 } 122 et.rollback(); 123 } 124 125 protected void releaseEntityManager(EntityManager em) { 126 if (!em.isOpen()) { 127 return; 128 } 129 try { 130 doCommit(em); 131 } finally { 132 if (em.isOpen()) { 133 em.clear(); 134 em.close(); 135 } 136 } 137 } 138 139 public void releaseEntityManagerWithRollback(EntityManager em) { 140 if (!em.isOpen()) { 141 return; 142 } 143 try { 144 doRollback(em); 145 } finally { 146 if (em.isOpen()) { 147 em.clear(); 148 em.close(); 149 } 150 } 151 } 152 153 public interface RunCallback<T> { 154 T runWith(EntityManager em); 155 } 156 157 public <T> T run(Boolean needActiveSession, RunCallback<T> callback) { 158 // needActiveSession now unused 159 Thread myThread = Thread.currentThread(); 160 ClassLoader lastLoader = myThread.getContextClassLoader(); 161 myThread.setContextClassLoader(getClass().getClassLoader()); 162 try { // insure context class loader restoring 163 EntityManager em = doAcquireEntityManager(); 164 doBegin(em); 165 try { // insure entity manager releasing 166 return callback.runWith(em); 167 } finally { 168 releaseEntityManager(em); 169 } 170 } finally { 171 myThread.setContextClassLoader(lastLoader); 172 } 173 } 174 175 public interface RunVoid { 176 void runWith(EntityManager em); 177 } 178 179 public void run(Boolean needActiveSession, RunVoid callback) { 180 // needActiveSession now unused 181 Thread myThread = Thread.currentThread(); 182 ClassLoader lastLoader = myThread.getContextClassLoader(); 183 myThread.setContextClassLoader(getClass().getClassLoader()); 184 try { // insure context class loader restoring 185 EntityManager em = doAcquireEntityManager(); 186 doBegin(em); 187 try { // insure entity manager releasing 188 callback.runWith(em); 189 } finally { 190 releaseEntityManager(em); 191 } 192 } finally { 193 myThread.setContextClassLoader(lastLoader); 194 } 195 } 196 197}