/* * Copyright 2008 Whohoo Licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable * law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the specific * language governing permissions and limitations under the License. */ package com.googlecode.mycontainer.jpa; import java.util.HashMap; import java.util.Map; import javax.naming.Context; import javax.naming.Name; import javax.naming.NameNotFoundException; import javax.naming.NamingException; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.spi.PersistenceProvider; import javax.persistence.spi.PersistenceUnitInfo; import javax.transaction.Status; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import com.googlecode.mycontainer.jta.TxEntry; import com.googlecode.mycontainer.kernel.KernelRuntimeException; import com.googlecode.mycontainer.kernel.ShutdownHook; import com.googlecode.mycontainer.kernel.deploy.DeployException; import com.googlecode.mycontainer.kernel.deploy.Deployer; import com.googlecode.mycontainer.kernel.deploy.SimpleDeployer; import com.googlecode.mycontainer.kernel.interceptors.AbstractIntercetorDeployer; import com.googlecode.mycontainer.kernel.naming.ObjectProvider; public abstract class JPADeployer extends Deployer implements ShutdownHook, ObjectProvider, SimpleDeployer { private static final long serialVersionUID = -5739685369847277589L; private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory .getLogger(JPADeployer.class); private String transcationManagerName = "TransactionManager"; private PersistenceUnitInfo info = new JPAInfoBuilder(); private EntityManagerFactory emf; private String sessionInterceptorDeployer = "StatelessDeployer/intercetorDeployerName"; public String getSessionInterceptorDeployer() { return sessionInterceptorDeployer; } public void setSessionInterceptorDeployer(String sessionInterceptorDeployer) { this.sessionInterceptorDeployer = sessionInterceptorDeployer; } public String getTranscationManagerName() { return transcationManagerName; } public void setTranscationManagerName(String transcationManagerName) { this.transcationManagerName = transcationManagerName; } public String getEntityManagerName() { String name = info.getPersistenceUnitName(); return name; } public PersistenceUnitInfo getInfo() { ((JPAInfoBuilder) this.info).setContext(getContext()); return info; } public void setInfo(PersistenceUnitInfo info) { this.info = info; } public void deploy() { overrrideConfig(info); TransactionManager tm = null; try { Context ctx = getContext(); AbstractIntercetorDeployer interceptorDeployer = (AbstractIntercetorDeployer) ctx .lookup(sessionInterceptorDeployer); interceptorDeployer .addContextInterceptor(PersistenceContextInterceptor.class); String name = getEntityManagerName(); LOG.info("Deploying: " + name); PersistenceProvider conf = getPersistenceProvider(); tm = getTransactionManager(info); tm.begin(); emf = conf.createContainerEntityManagerFactory(info, null); ctx.bind(name, this); getKernel().addShutdownHook(this); tm.commit(); } catch (RuntimeException e) { if (tm != null) { try { tm.rollback(); } catch (Exception e1) { LOG.error("Error rollback", e1); } } throw e; } catch (Exception e) { if (tm != null) { try { tm.rollback(); } catch (Exception e1) { LOG.error("Error rollback", e1); } } throw new DeployException(e); } } protected abstract PersistenceProvider getPersistenceProvider(); protected abstract void overrrideConfig(PersistenceUnitInfo info); protected abstract TransactionManager getTransactionManager( PersistenceUnitInfo info); public void shutdown() { TransactionManager tm = null; try { tm = getTransactionManager(info); tm.begin(); Context ctx = getContext(); String name = getEntityManagerName(); LOG.info("Undeploying: " + name); emf.close(); ctx.unbind(name); tm.commit(); } catch (RuntimeException e) { try { tm.rollback(); } catch (Exception e1) { LOG.error("Error rollback", e1); } throw e; } catch (Exception e) { try { tm.rollback(); } catch (Exception e1) { LOG.error("Error rollback", e1); } throw new DeployException(e); } } public Object provide(Name name) { try { TransactionManager tm = getTransactionManager(info); if (tm.getStatus() == Status.STATUS_NO_TRANSACTION) { return emf.createEntityManager(); } Transaction tx = tm.getTransaction(); TxEntry entry = new TxEntry(tx, getEntityManagerName()); Map<TxEntry, EntityManager> ems = lookupEntityManagers(); EntityManager ret = ems.get(entry); if (ret != null) { return ret; } ret = emf.createEntityManager(); ems.put(entry, ret); return ret; } catch (SystemException e) { throw new KernelRuntimeException(e); } } @SuppressWarnings("unchecked") private Map<TxEntry, EntityManager> lookupEntityManagers() { Context ctx = getContext(); try { try { Map<TxEntry, EntityManager> ret = (Map<TxEntry, EntityManager>) ctx .lookup("tl/jpa/persistences"); return ret; } catch (NameNotFoundException e) { Map<TxEntry, EntityManager> ret = new HashMap<TxEntry, EntityManager>(); ctx.bind("tl/jpa/persistences", ret); return ret; } } catch (NamingException e) { throw new KernelRuntimeException(e); } } @Override public void setContext(Context context) { super.setContext(context); ((JPAInfoBuilder) this.info).setContext(context); } }