/* * $Id: IDOContainer.java,v 1.28 2009/04/22 12:50:56 valdas Exp $ * Created in 2002 by Tryggvi Larusson * * Copyright (C) 2002-2006 Idega software hf. All Rights Reserved. * * This software is the proprietary information of Idega hf. Use is subject to * license terms. * */ package com.idega.data; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.EntityBean; import javax.ejb.FinderException; import com.idega.repository.data.Instantiator; import com.idega.repository.data.Singleton; import com.idega.repository.data.SingletonRepository; import com.idega.util.datastructures.HashtableDoubleKeyed; /** * <p> * IDOContainer is the central service for the IDO persistence Framework.<br/> * This class is a singleton for the application and is the "base center" for * getting access to other component of the persistence engine. * </p> * Last modified: $Date: 2009/04/22 12:50:56 $ by $Author: valdas $ * * @author <a href="mailto:tryggvil@idega.com">Tryggvi Larusson</a> * @version $Revision: 1.28 $ */ public class IDOContainer implements Singleton { // Static variables: private static Instantiator instantiator = new Instantiator() { @Override public Object getInstance() { return new IDOContainer(); } }; // Instance variables: // this instance variable sets if beancaching is active by default for all // entities private boolean beanCachingActiveByDefault = false; private boolean queryCachingActive = false; private Map<Class<?>, List<?>> emptyBeanInstances; private Map<String, Map<Class<?>, IDOBeanCache>> beanCacheMap; private Map<Class<?>, Boolean> isBeanCacheActive; // These variables were moved from GenericEntity: private Map<Class<?>, IDOEntityDefinition> entityAttributes; private Map<Class<?>, IDOEntity> entityStaticInstances; private HashtableDoubleKeyed<String, EntityRelationship> relationshipTables = new HashtableDoubleKeyed<String, EntityRelationship>(); protected IDOContainer() { // unload } public static IDOContainer getInstance() { return (IDOContainer) SingletonRepository.getRepository().getInstance(IDOContainer.class, instantiator); } protected Map<Class<?>, List<?>> getBeanMap() { if (this.emptyBeanInstances == null) { this.emptyBeanInstances = new HashMap<Class<?>, List<?>>(); } return this.emptyBeanInstances; } /** * <p> * Map with all datasources and hashmaps for beancache for each datasource.<br/> * Keys are datasourceNames and values are Maps for each datasource. * </p> * * @return */ protected Map<String, Map<Class<?>, IDOBeanCache>> getDatasourcesBeanCacheMaps() { if (this.beanCacheMap == null) { this.beanCacheMap = new HashMap<String, Map<Class<?>, IDOBeanCache>>(); } return this.beanCacheMap; } /** * <p> * Gets a BeanCacheMap for each datasource, where the key is a * entityInterfacesClass (Class) and value is a IDOBeanCache instance. * </p> * * @param dataSource * @return */ protected Map<Class<?>, IDOBeanCache> getBeanCacheMap(String dataSource) { Map<String, Map<Class<?>, IDOBeanCache>> bCacheMap = getDatasourcesBeanCacheMaps(); Map<Class<?>, IDOBeanCache> dataSourceMap = bCacheMap.get(dataSource); if (dataSourceMap == null) { dataSourceMap = new HashMap<Class<?>, IDOBeanCache>(); bCacheMap.put(dataSource, dataSourceMap); } return dataSourceMap; } protected Map<Class<?>, Boolean> getIsBeanCachActiveMap() { if (this.isBeanCacheActive == null) { this.isBeanCacheActive = new HashMap<Class<?>, Boolean>(); } return this.isBeanCacheActive; } protected IDOBeanCache getBeanCache(String datasource, Class<? extends IDOEntity> entityInterfaceClass) { IDOBeanCache idobc = getBeanCacheMap(datasource).get(entityInterfaceClass); if (idobc == null) { idobc = new IDOBeanCache(entityInterfaceClass, datasource); getBeanCacheMap(datasource).put(entityInterfaceClass, idobc); } return idobc; } protected List<?> getFreeBeansList(Class<? extends IDOEntity> entityInterfaceClass) { List<?> l = getBeanMap().get(entityInterfaceClass); if (l == null) { l = new ArrayList<Object>(); } getBeanMap().put(entityInterfaceClass, l); return l; } protected <T extends IDOEntity> T getFreeBeanInstance(Class<T> entityInterfaceClass) throws Exception { T entity = null; /* * List l = getFreeBeansList(entityInterfaceClass); if(!l.isEmpty()){ * entity= (IDOEntity)l.get(0); } */ if (entity == null) { entity = this.instanciateBean(entityInterfaceClass); } return entity; } public <T extends IDOEntity> T createEntity(Class<T> entityInterfaceClass) throws javax.ejb.CreateException { try { T entity = null; try { entity = getFreeBeanInstance(entityInterfaceClass); } catch (Error e) { System.err.println("[idoContainer] : Error creating bean for " + entityInterfaceClass.getName()); e.printStackTrace(); } ((EntityBean) entity).ejbActivate(); ((IDOEntityBean) entity).ejbCreate(); return entity; } catch (Exception e) { e.printStackTrace(); throw new IDOCreateException(e); } } protected <T extends IDOEntity> T instanciateBean(Class<T> entityInterfaceClass) throws Exception { Class<T> beanClass = null; T entity = null; try { beanClass = IDOLookup.getBeanClassFor(entityInterfaceClass); } catch (Error t) { System.err.println("Error looking up bean class for bean: " + entityInterfaceClass.getName()); t.printStackTrace(); } try { entity = beanClass.newInstance(); } catch (Error t) { System.err.println("Error instanciating bean class for bean: " + entityInterfaceClass.getName()); t.printStackTrace(); } return entity; } /** * To find the data by a primary key (cached if appropriate), usually called * by HomeImpl classes */ public <T extends IDOEntity> T findByPrimaryKey(Class<T> entityInterfaceClass, Object pk, IDOHome home) throws javax.ejb.FinderException { return findByPrimaryKey(entityInterfaceClass, pk, null, home); } /** * To find the data by a primary key (cached if appropriate), usually called * by HomeImpl classes */ <T extends IDOEntity> T findByPrimaryKey(Class<T> entityInterfaceClass, Object pk, IDOHome home, String dataSourceName) throws javax.ejb.FinderException { return findByPrimaryKey(entityInterfaceClass, pk, null, home, dataSourceName); } /** * Workaround to speed up finders where the ResultSet is already created */ <T extends IDOEntity> T findByPrimaryKey(Class<T> entityInterfaceClass, Object pk, java.sql.ResultSet rs, IDOHome home) throws javax.ejb.FinderException { return findByPrimaryKey(entityInterfaceClass, pk, rs, home, null); } /** * Workaround to speed up finders where the ResultSet is already created */ <T extends IDOEntity> T findByPrimaryKey( Class<T> entityInterfaceClass, Object pk, java.sql.ResultSet rs, IDOHome home, String dataSourceName ) throws javax.ejb.FinderException { try { T entity = null; IDOBeanCache cache = null; boolean useBeanCaching = beanCachingActive(entityInterfaceClass); if (useBeanCaching) { cache = this.getBeanCache(dataSourceName, entityInterfaceClass); entity = cache.getCachedEntity(pk); } if (entity == null) { entity = this.instanciateBean(entityInterfaceClass); if (dataSourceName != null) { try { ((GenericEntity) entity).setDatasource(dataSourceName); } catch (ClassCastException ce) { ce.printStackTrace(); } } /** * @todo */ ((IDOEntityBean) entity).ejbFindByPrimaryKey(pk); if (rs != null) { ((GenericEntity) entity).preEjbLoad(rs); } else { ((IDOEntityBean) entity).ejbLoad(); } ((IDOEntityBean) entity).setEJBLocalHome(home); if (useBeanCaching) { cache.putCachedEntity(pk, entity); } } return entity; } catch (Exception e) { // Logger.getLogger(getClass().getName()).log(Level.WARNING, "Error getting by primary key: " + pk + " ("+pk.getClass()+")", e); throw new FinderException(e.getMessage()); } } /** * <p> * Sets if the beanCaching is active by default for all entities * </p> * * @param onOrOff */ public synchronized void setBeanCachingActiveByDefault(boolean active) { if (!active) { this.flushAllBeanCache(); } this.beanCachingActiveByDefault = active; } /** * * @param entityInterfaceClass * @return returns true if bean cashing is active for all entities or if it * is active for this entityInterfaceClass */ protected <T extends IDOEntity> boolean beanCachingActive(Class<T> entityInterfaceClass) { Boolean isActive = getIsBeanCachActiveMap().get(entityInterfaceClass); if (isActive == null) { try { IDOEntityDefinition def = IDOLookup.getEntityDefinitionForClass(entityInterfaceClass); isActive = def.isBeanCachingActive(); } catch (IDOLookupException t) { System.err.println("Error looking up entity defitition for bean: " + entityInterfaceClass.getName()); t.printStackTrace(); } if (isActive == null) { // still null, use system-default isActive = ((this.beanCachingActiveByDefault) ? Boolean.TRUE : Boolean.FALSE); } getIsBeanCachActiveMap().put(entityInterfaceClass, isActive); } return isActive.booleanValue(); } public synchronized void setQueryCaching(boolean onOrOff) { if (!onOrOff) { this.flushAllQueryCache(); } this.isBeanCacheActive = null; // remove at least all elements useing // system-default (queryCachingActive) this.queryCachingActive = onOrOff; } protected <T extends IDOEntity> boolean queryCachingActive(Class<T> entityInterfaceClass) { return this.queryCachingActive; } <T extends IDOEntity> T getPooledInstance(Class<T> entityInterfaceClass) { return null; } public synchronized void flushAllCache() { this.flushAllBeanCache(); this.flushAllQueryCache(); } public synchronized void flushAllBeanCache() { Iterator<String> dsIterator = getDatasourcesBeanCacheMaps().keySet().iterator(); while (dsIterator.hasNext()) { String dataSource = dsIterator.next(); Iterator<Class<?>> iter = getBeanCacheMap(dataSource).keySet().iterator(); while (iter.hasNext()) { @SuppressWarnings("unchecked") Class<IDOEntity> interfaceClass = (Class<IDOEntity>) iter.next(); this.getBeanCache(dataSource, interfaceClass).flushAllBeanCache(); } } Logger.getLogger(this.getClass().getName()).log(Level.INFO, "[idoContainer] Flushed all Bean Cache"); } public synchronized void flushAllQueryCache() { if (this.queryCachingActive) { Iterator<String> dsIterator = getDatasourcesBeanCacheMaps().keySet().iterator(); while (dsIterator.hasNext()) { String dataSource = dsIterator.next(); Iterator<Class<?>> iter = getBeanCacheMap(dataSource).keySet().iterator(); while (iter.hasNext()) { @SuppressWarnings("unchecked") Class<IDOEntity> interfaceClass = (Class<IDOEntity>) iter.next(); this.getBeanCache(dataSource, interfaceClass).flushAllQueryCache(); } } Logger.getLogger(this.getClass().getName()).log(Level.INFO, "[idoContainer] Flushed all Query Cache"); } } /** * Map Used by the IDO Framework and stores a static instance of a * IDOEntityDefinition. This map has as a key a Class instance and a value a * IDOEntityDefinition instance. * * @return Returns the entityAttributes. */ Map<Class<?>, IDOEntityDefinition> getEntityDefinitions() { if (this.entityAttributes == null) { this.entityAttributes = new HashMap<Class<?>, IDOEntityDefinition>(); } return this.entityAttributes; } /** * Map Used by the IDO Framework and stores a static instance of a * IDOEntity. This map has as a key a Class instance and a value a IDOEntity * instance. */ Map<Class<?>, IDOEntity> getEntityStaticInstances() { if (this.entityStaticInstances == null) { this.entityStaticInstances = new HashMap<Class<?>, IDOEntity>(); } return this.entityStaticInstances; } /** * Map used to look up relationships (Many-to-many) between tables.<br> * The keys here are two Strings (the EntityNames or TableNames for the * Entity beans that have the relationship) and as a value an instance of * EntityRelationship. * * @return the relationship Map */ HashtableDoubleKeyed<String, EntityRelationship> getRelationshipTableMap() { if (this.relationshipTables == null) { this.relationshipTables = new HashtableDoubleKeyed<String, EntityRelationship>(); } return this.relationshipTables; } private DatastoreInterfaceManager datastoreInterfaceManager; /** * @return Returns the datastoreInterfaceManager. */ public DatastoreInterfaceManager getDatastoreInterfaceManager() { if (this.datastoreInterfaceManager == null) { this.datastoreInterfaceManager = new DatastoreInterfaceManager(); } return this.datastoreInterfaceManager; } /** * @param datastoreInterfaceManager * The datastoreInterfaceManager to set. */ public void setDatastoreInterfaceManager(DatastoreInterfaceManager datastoreInterfaceManager) { this.datastoreInterfaceManager = datastoreInterfaceManager; } }