/* * Hibernate, Relational Persistence for Idiomatic Java * * JBoss, Home of Professional Open Source * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors * as indicated by the @authors tag. All rights reserved. * See the copyright.txt in the distribution for a * full listing of individual contributors. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License, v. 2.1. * This program is distributed in the hope that it will be useful, but WITHOUT A * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public License, * v.2.1 along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package org.hibernate.ogm.jpa; import java.net.URL; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.persistence.EntityManagerFactory; import javax.persistence.PersistenceException; import javax.persistence.spi.PersistenceProvider; import javax.persistence.spi.PersistenceUnitInfo; import javax.persistence.spi.PersistenceUnitTransactionType; import javax.persistence.spi.ProviderUtil; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.EJB3DTDEntityResolver; import org.hibernate.cfg.Environment; import org.hibernate.ejb.AvailableSettings; import org.hibernate.ejb.HibernatePersistence; import org.hibernate.ejb.packaging.PersistenceMetadata; import org.hibernate.ejb.packaging.PersistenceXmlLoader; import org.hibernate.ogm.cfg.OgmConfiguration; import org.hibernate.ogm.cfg.impl.OgmNamingStrategy; import org.hibernate.ogm.jpa.impl.DelegatorPersistenceUnitInfo; import org.hibernate.ogm.jpa.impl.OgmEntityManagerFactory; import org.hibernate.ogm.jpa.impl.OgmIdentifierGeneratorStrategyProvider; import org.hibernate.ogm.util.impl.Log; import org.hibernate.ogm.util.impl.LoggerFactory; /** * JPA PersistenceProvider implementation specific to Hibernate OGM * All specific configurations are set transparently for the user. * * @author Emmanuel Bernard <emmanuel@hibernate.org> */ public class HibernateOgmPersistence implements PersistenceProvider { private static String IMPLEMENTATION_NAME = HibernateOgmPersistence.class.getName(); private HibernatePersistence delegate = new HibernatePersistence(); private static final Log log = LoggerFactory.make(); private static final Map EMPTY_MAP = new HashMap<Object, Object>( 0 ); @Override public EntityManagerFactory createEntityManagerFactory(String emName, Map map) { try { Map integration = map == null ? EMPTY_MAP : Collections.unmodifiableMap( map ); Enumeration<URL> persistenceXml = Thread.currentThread() .getContextClassLoader() .getResources( "META-INF/persistence.xml" ); if ( ! persistenceXml.hasMoreElements() ) { log.persistenceXmlNotFoundInClassPath( emName != null ? emName : "" ); } while ( persistenceXml.hasMoreElements() ) { URL url = persistenceXml.nextElement(); List<PersistenceMetadata> metadataFiles = PersistenceXmlLoader.deploy( url, integration, new EJB3DTDEntityResolver(), PersistenceUnitTransactionType.RESOURCE_LOCAL ); for ( PersistenceMetadata metadata : metadataFiles ) { //if the provider is not set, don't use it as people might want to use Hibernate ORM if ( IMPLEMENTATION_NAME.equalsIgnoreCase( metadata.getProvider() ) ) { //correct provider Map<Object,Object> protectiveCopy = new HashMap<Object,Object>(integration); enforceOgmConfig( protectiveCopy ); protectiveCopy.put( HibernatePersistence.PROVIDER, delegate.getClass().getName() ); final EntityManagerFactory coreEMF = delegate.createEntityManagerFactory( emName, protectiveCopy ); if ( coreEMF != null ) { //delegate might return null to refuse the configuration //(like when the configuration file is not defining the expected persistent unit) return new OgmEntityManagerFactory( coreEMF ); } } } } //not the right provider return null; } catch (PersistenceException pe) { throw (PersistenceException) pe; } catch (Exception e) { throw new PersistenceException( "Unable to build EntityManagerFactory", e ); } } private void enforceOgmConfig(Map<Object,Object> map) { map.put( AvailableSettings.NAMING_STRATEGY, OgmNamingStrategy.class.getName() ); //we use a placeholder DS to make sure, Hibernate EntityManager (Ejb3Configuration) does not enforce a different connection provider map.put( Environment.DATASOURCE, "---PlaceHolderDSForOGM---" ); map.put( AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER, OgmIdentifierGeneratorStrategyProvider.class.getName()); map.put( Configuration.USE_NEW_ID_GENERATOR_MAPPINGS, "true" ); //needed to guarantee the table id generator mapping map.put( OgmConfiguration.OGM_ON, "true" ); } @Override public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) { final String persistenceProviderClassName = info.getPersistenceProviderClassName(); if ( persistenceProviderClassName == null || IMPLEMENTATION_NAME.equals( persistenceProviderClassName ) ) { Map<Object,Object> protectiveCopy = map != null ? new HashMap<Object,Object>(map) : new HashMap<Object,Object>(); enforceOgmConfig( protectiveCopy ); //HEM only builds an EntityManagerFactory when HibernatePersistence.class.getName() is the PersistenceProvider //that's why we override it when //new DelegatorPersistenceUnitInfo(info) final EntityManagerFactory coreEMF = delegate.createContainerEntityManagerFactory( new DelegatorPersistenceUnitInfo( info ), protectiveCopy ); if ( coreEMF != null ) { //delegate might return null to refuse the configuration //(like when the configuration file is not defining the expected persistent unit) return new OgmEntityManagerFactory( coreEMF ); } } //not the right provider return null; } @Override public ProviderUtil getProviderUtil() { return delegate.getProviderUtil(); } }