1
package com.eucalyptus.entities;
5
import java.util.concurrent.ConcurrentSkipListMap;
6
import java.util.concurrent.atomic.AtomicInteger;
7
import javax.persistence.MappedSuperclass;
8
import javax.persistence.PersistenceContext;
9
import org.apache.log4j.Logger;
10
import org.hibernate.ejb.Ejb3Configuration;
11
import org.hibernate.ejb.EntityManagerFactoryImpl;
12
import com.eucalyptus.bootstrap.BootstrapException;
13
import com.eucalyptus.records.EventType;
14
import com.eucalyptus.system.Ats;
15
import com.eucalyptus.util.LogUtil;
16
import com.google.common.collect.ArrayListMultimap;
17
import com.google.common.collect.Lists;
18
import com.google.common.collect.Multimaps;
19
import edu.emory.mathcs.backport.java.util.Collections;
20
import com.eucalyptus.records.EventRecord;
22
@SuppressWarnings( "unchecked" )
23
public class PersistenceContexts {
24
public static int MAX_FAIL = 5;
25
private static AtomicInteger failCount = new AtomicInteger( 0 );
26
private static Logger LOG = Logger.getLogger( PersistenceContexts.class );
27
private static final ArrayListMultimap<String, Class> entities = Multimaps.newArrayListMultimap( );
28
private static final List<Class> sharedEntities = Lists.newArrayList( );
29
private static Map<String, EntityManagerFactoryImpl> emf = new ConcurrentSkipListMap<String, EntityManagerFactoryImpl>( );
30
private static List<Exception> illegalAccesses = Collections.synchronizedList( Lists.newArrayList( ) );
32
static void addEntity( Class entity ) {
33
if ( !isDuplicate( entity ) ) {
34
String ctxName = Ats.from( entity ).get( PersistenceContext.class ).name( );
35
EventRecord.here( PersistenceContextDiscovery.class, EventType.PERSISTENCE_ENTITY_REGISTERED, ctxName, entity.getCanonicalName( ) ).info( );
36
entities.put( ctxName, entity );
40
static void addSharedEntity( Class entity ) {
41
if ( !isDuplicate( entity ) ) {
42
EventRecord.here( PersistenceContextDiscovery.class, EventType.PERSISTENCE_ENTITY_REGISTERED, "shared", entity.getCanonicalName( ) ).info( );
43
sharedEntities.add( entity );
47
private static boolean isDuplicate( Class entity ) {
48
PersistenceContext ctx = Ats.from( entity ).get( PersistenceContext.class );
49
if( Ats.from( entity ).has( MappedSuperclass.class ) ) {
51
} else if ( ctx == null || ctx.name( ) == null ) {
52
RuntimeException ex = new RuntimeException( "Failed to register broken entity class: " + entity.getCanonicalName( ) + ". Ensure that the class has a well-formed @PersistenceContext annotation.");
55
} else if ( sharedEntities.contains( entity ) ) {
56
Class old = sharedEntities.get( sharedEntities.indexOf( entity ) );
57
LOG.error( "Duplicate entity definition detected: " + entity.getCanonicalName( ) );
58
LOG.error( "=> OLD: " + old.getProtectionDomain( ).getCodeSource( ).getLocation( ) );
59
LOG.error( "=> NEW: " + entity.getProtectionDomain( ).getCodeSource( ).getLocation( ) );
60
throw BootstrapException.throwFatal( "Duplicate entity definition in shared entities: " + entity.getCanonicalName( ) + ". See error logs for details." );
61
} else if ( entities.get( ctx.name( ) ) != null && entities.get( ctx.name( ) ).contains( entity ) ) {
62
List<Class> context = entities.get( ctx.name( ) );
63
Class old = context.get( context.indexOf( entity ) );
64
LOG.error( "Duplicate entity definition detected: " + entity.getCanonicalName( ) );
65
LOG.error( "=> OLD: " + old.getProtectionDomain( ).getCodeSource( ).getLocation( ) );
66
LOG.error( "=> NEW: " + entity.getProtectionDomain( ).getCodeSource( ).getLocation( ) );
67
throw BootstrapException.throwFatal( "Duplicate entity definition in '" + ctx.name( ) + "': " + entity.getCanonicalName( ) + ". See error logs for details." );
73
public static EntityManagerFactoryImpl registerPersistenceContext( final String persistenceContext, final Ejb3Configuration config ) {
74
synchronized ( PersistenceContexts.class ) {
75
if ( illegalAccesses != null && !illegalAccesses.isEmpty( ) ) {
76
for ( Exception e : illegalAccesses ) {
79
LogUtil.header( "Illegal Access to Persistence Context. Database not yet configured. This is always a BUG: " + persistenceContext );
81
} else if ( !emf.containsKey( persistenceContext ) ) {
82
illegalAccesses = null;
83
EntityManagerFactoryImpl entityManagerFactory = ( EntityManagerFactoryImpl ) config.buildEntityManagerFactory( );
84
LOG.info( "-> Setting up persistence context for : " + persistenceContext );
85
LOG.info( LogUtil.subheader( LogUtil.dumpObject( config ) ) );
86
emf.put( persistenceContext, entityManagerFactory );
88
return emf.get( persistenceContext );
92
public static List<String> list( ) {
93
return Lists.newArrayList( entities.keySet( ) );
96
public static List<Class> listEntities( String persistenceContext ) {
97
return entities.get( persistenceContext );
100
public static void handleConnectionError( Throwable cause ) {
104
private static void touchDatabase( ) {
105
if ( MAX_FAIL > failCount.getAndIncrement( ) ) {
106
LOG.fatal( LogUtil.header( "Database connection failure limit reached (" + MAX_FAIL + "): HUPping the system." ) );
109
LOG.warn( LogUtil.subheader( "Error using or obtaining a database connection, fail count is " + failCount.intValue( ) + " (max=" + MAX_FAIL
110
+ ") more times before reloading." ) );
114
@SuppressWarnings( "deprecation" )
115
public static EntityManagerFactoryImpl getEntityManagerFactory( final String persistenceContext ) {
116
if ( !emf.containsKey( persistenceContext ) ) {
117
RuntimeException e = new RuntimeException( "Attempting to access an entity wrapper before the database has been configured: " + persistenceContext + ". The available contexts are: " + emf.keySet( ));
118
illegalAccesses = illegalAccesses == null ? Collections.synchronizedList( Lists.newArrayList( ) ) : illegalAccesses;
119
illegalAccesses.add( e );
122
return emf.get( persistenceContext );
125
public static void shutdown() {
126
for( String ctx : emf.keySet( ) ) {
127
EntityManagerFactoryImpl em = emf.get( ctx );
129
LOG.info( "Closing persistence context: " + ctx );
132
LOG.info( "Closing persistence context: " + ctx + " (found it closed already)" );