0001: /*
0002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003: *
0004: * This file is part of Resin(R) Open Source
0005: *
0006: * Each copy or derived work must preserve the copyright notice and this
0007: * notice unmodified.
0008: *
0009: * Resin Open Source is free software; you can redistribute it and/or modify
0010: * it under the terms of the GNU General Public License as published by
0011: * the Free Software Foundation; either version 2 of the License, or
0012: * (at your option) any later version.
0013: *
0014: * Resin Open Source is distributed in the hope that it will be useful,
0015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017: * of NON-INFRINGEMENT. See the GNU General Public License for more
0018: * details.
0019: *
0020: * You should have received a copy of the GNU General Public License
0021: * along with Resin Open Source; if not, write to the
0022: *
0023: * Free Software Foundation, Inc.
0024: * 59 Temple Place, Suite 330
0025: * Boston, MA 02111-1307 USA
0026: *
0027: * @author Scott Ferguson
0028: */
0029:
0030: package com.caucho.amber.manager;
0031:
0032: import com.caucho.amber.AmberException;
0033: import com.caucho.amber.AmberRuntimeException;
0034: import com.caucho.amber.cfg.BaseConfigIntrospector;
0035: import com.caucho.amber.cfg.EmbeddableIntrospector;
0036: import com.caucho.amber.cfg.EntityIntrospector;
0037: import com.caucho.amber.cfg.EntityMappingsConfig;
0038: import com.caucho.amber.cfg.MappedSuperIntrospector;
0039: import com.caucho.amber.cfg.NamedNativeQueryConfig;
0040: import com.caucho.amber.cfg.SqlResultSetMappingConfig;
0041: import com.caucho.amber.entity.AmberCompletion;
0042: import com.caucho.amber.entity.AmberEntityHome;
0043: import com.caucho.amber.entity.Entity;
0044: import com.caucho.amber.entity.EntityItem;
0045: import com.caucho.amber.entity.EntityKey;
0046: import com.caucho.amber.entity.Listener;
0047: import com.caucho.amber.gen.AmberGenerator;
0048: import com.caucho.amber.gen.AmberGeneratorImpl;
0049: import com.caucho.amber.idgen.IdGenerator;
0050: import com.caucho.amber.idgen.SequenceIdGenerator;
0051: import com.caucho.amber.query.AbstractQuery;
0052: import com.caucho.amber.query.QueryCacheKey;
0053: import com.caucho.amber.query.ResultSetCacheChunk;
0054: import com.caucho.amber.table.Table;
0055: import com.caucho.amber.type.*;
0056: import com.caucho.bytecode.JClass;
0057: import com.caucho.bytecode.JClassLoader;
0058: import com.caucho.bytecode.JMethod;
0059: import com.caucho.config.ConfigException;
0060: import com.caucho.java.gen.JavaClassGenerator;
0061: import com.caucho.jdbc.JdbcMetaData;
0062: import com.caucho.naming.Jndi;
0063: import com.caucho.util.L10N;
0064: import com.caucho.util.LruCache;
0065: import com.caucho.webbeans.manager.*;
0066:
0067: import javax.persistence.EntityManager;
0068: import javax.sql.DataSource;
0069: import java.io.IOException;
0070: import java.lang.ref.SoftReference;
0071: import java.sql.ResultSetMetaData;
0072: import java.util.ArrayList;
0073: import java.util.Collection;
0074: import java.util.HashMap;
0075: import java.util.Iterator;
0076: import java.util.logging.Level;
0077: import java.util.logging.Logger;
0078:
0079: /**
0080: * Main interface between Resin and the connector. It's the
0081: * top-level SPI class for creating the SPI ManagedConnections.
0082: *
0083: * The resource configuration in Resin's web.xml will use bean-style
0084: * configuration to configure the ManagecConnectionFactory.
0085: */
0086: public class AmberPersistenceUnit {
0087: private static final L10N L = new L10N(AmberPersistenceUnit.class);
0088: private static final Logger log = Logger
0089: .getLogger(AmberPersistenceUnit.class.getName());
0090:
0091: private String _name;
0092:
0093: private boolean _isJPA;
0094:
0095: private AmberContainer _amberContainer;
0096:
0097: // Actual class is EntityManagerProxy, but EntityManager is JDK 1.5 dependent
0098: private Object _entityManagerProxy;
0099:
0100: // basic data source
0101: private DataSource _dataSource;
0102:
0103: // data source for read-only requests
0104: private DataSource _readDataSource;
0105:
0106: // data source for requests in a transaction
0107: private DataSource _xaDataSource;
0108:
0109: // persistence.xml jta-data-source
0110: private DataSource _jtaDataSource;
0111: // persistence.xml non-jta-data-source
0112: private DataSource _nonJtaDataSource;
0113:
0114: private JdbcMetaData _jdbcMetaData;
0115:
0116: private boolean _createDatabaseTables;
0117: private boolean _validateDatabaseTables = true;
0118:
0119: // private long _tableCacheTimeout = 250;
0120: private long _tableCacheTimeout = 2000;
0121:
0122: private TypeManager _typeManager = new TypeManager();
0123:
0124: // loader override for ejb
0125: private ClassLoader _enhancedLoader;
0126:
0127: private HashMap<String, Table> _tableMap = new HashMap<String, Table>();
0128:
0129: private HashMap<String, AmberEntityHome> _entityHomeMap = new HashMap<String, AmberEntityHome>();
0130:
0131: private HashMap<String, IdGenerator> _tableGenMap = new HashMap<String, IdGenerator>();
0132:
0133: private HashMap<String, SequenceIdGenerator> _sequenceGenMap = new HashMap<String, SequenceIdGenerator>();
0134:
0135: private LruCache<String, AbstractQuery> _queryParseCache = new LruCache<String, AbstractQuery>(
0136: 1024);
0137:
0138: private LruCache<QueryCacheKey, SoftReference<ResultSetCacheChunk>> _queryCache = new LruCache<QueryCacheKey, SoftReference<ResultSetCacheChunk>>(
0139: 1024);
0140:
0141: private LruCache<QueryCacheKey, SoftReference<ResultSetMetaData>> _queryCacheMetaData = new LruCache<QueryCacheKey, SoftReference<ResultSetMetaData>>(
0142: 16);
0143:
0144: private LruCache<EntityKey, SoftReference<EntityItem>> _entityCache = new LruCache<EntityKey, SoftReference<EntityItem>>(
0145: 32 * 1024);
0146:
0147: private EntityKey _entityKey = new EntityKey();
0148:
0149: private ArrayList<EntityType> _lazyConfigure = new ArrayList<EntityType>();
0150:
0151: private ArrayList<EntityType> _lazyGenerate = new ArrayList<EntityType>();
0152: private ArrayList<AmberEntityHome> _lazyHomeInit = new ArrayList<AmberEntityHome>();
0153: private ArrayList<Table> _lazyTable = new ArrayList<Table>();
0154:
0155: private HashMap<String, String> _namedQueryMap = new HashMap<String, String>();
0156:
0157: private HashMap<String, SqlResultSetMappingConfig> _sqlResultSetMap = new HashMap<String, SqlResultSetMappingConfig>();
0158:
0159: private HashMap<String, NamedNativeQueryConfig> _namedNativeQueryMap = new HashMap<String, NamedNativeQueryConfig>();
0160:
0161: private ArrayList<EntityMappingsConfig> _entityMappingsList;
0162:
0163: private ArrayList<EmbeddableType> _embeddableTypes = new ArrayList<EmbeddableType>();
0164:
0165: private ArrayList<MappedSuperclassType> _mappedSuperclassTypes = new ArrayList<MappedSuperclassType>();
0166:
0167: private ArrayList<ListenerType> _defaultListeners = new ArrayList<ListenerType>();
0168:
0169: private EntityIntrospector _entityIntrospector;
0170: private EmbeddableIntrospector _embeddableIntrospector;
0171: private MappedSuperIntrospector _mappedSuperIntrospector;
0172:
0173: private AmberGenerator _generator;
0174:
0175: // private boolean _supportsGetGeneratedKeys;
0176:
0177: private ThreadLocal<AmberConnection> _threadConnection = new ThreadLocal<AmberConnection>();
0178:
0179: private volatile boolean _isInit;
0180:
0181: private long _xid = 1;
0182:
0183: public AmberPersistenceUnit(AmberContainer container, String name) {
0184: _amberContainer = container;
0185: _name = name;
0186:
0187: _dataSource = container.getDataSource();
0188: _xaDataSource = container.getXADataSource();
0189: _readDataSource = container.getReadDataSource();
0190:
0191: _createDatabaseTables = container.getCreateDatabaseTables();
0192:
0193: _embeddableIntrospector = new EmbeddableIntrospector(this );
0194: _entityIntrospector = new EntityIntrospector(this );
0195: _mappedSuperIntrospector = new MappedSuperIntrospector(this );
0196:
0197: // needed to support JDK 1.4 compatibility
0198: try {
0199: bindProxy();
0200: } catch (Throwable e) {
0201: log.log(Level.FINE, e.toString(), e);
0202: }
0203: }
0204:
0205: public void setName(String name) {
0206: _name = name;
0207: }
0208:
0209: public String getName() {
0210: return _name;
0211: }
0212:
0213: private void bindProxy() throws Exception {
0214: String name = getName();
0215:
0216: // XXX: is "default" appropriate?
0217: // jpa/0s2m <=> tck: ejb30/persistence/ee/packaging/ejb/resource_local/test1
0218: if (name == null || "".equals(name))
0219: name = "default";
0220:
0221: WebBeansContainer webBeans = WebBeansContainer
0222: .create(_amberContainer.getParentClassLoader());
0223: webBeans
0224: .addSingleton(new AmberEntityManagerFactory(this ), name);
0225: webBeans.addSingleton(new EntityManagerProxy(this ), name);
0226: }
0227:
0228: public EntityManager getEntityManager() {
0229: // return (EntityManager) _entityManagerProxy;
0230:
0231: return null;
0232: }
0233:
0234: public AmberContainer getAmberContainer() {
0235: return _amberContainer;
0236: }
0237:
0238: public ClassLoader getEnhancedLoader() {
0239: if (_enhancedLoader != null)
0240: return _enhancedLoader;
0241: else
0242: return _amberContainer.getEnhancedLoader();
0243: }
0244:
0245: /**
0246: * EJB/CMP needs to set a special enhanced loader.
0247: */
0248: public void setEnhancedLoader(ClassLoader loader) {
0249: _enhancedLoader = loader;
0250: }
0251:
0252: /**
0253: * Sets the data source.
0254: */
0255: public void setDataSource(DataSource dataSource) {
0256: _dataSource = dataSource;
0257: }
0258:
0259: /**
0260: * Gets the data source.
0261: */
0262: public DataSource getDataSource() {
0263: if (_jtaDataSource != null)
0264: return _jtaDataSource;
0265: else if (_nonJtaDataSource != null)
0266: return _nonJtaDataSource;
0267: else if (_dataSource != null)
0268: return _dataSource;
0269: else {
0270: return _amberContainer.getDataSource();
0271: }
0272: }
0273:
0274: /**
0275: * Sets the read data source.
0276: */
0277: public void setReadDataSource(DataSource dataSource) {
0278: _readDataSource = dataSource;
0279: }
0280:
0281: /**
0282: * Gets the read data source.
0283: */
0284: public DataSource getReadDataSource() {
0285: return _readDataSource;
0286: }
0287:
0288: /**
0289: * Sets the XA data source.
0290: */
0291: public void setXADataSource(DataSource dataSource) {
0292: _xaDataSource = dataSource;
0293: }
0294:
0295: /**
0296: * Gets the xa data source.
0297: */
0298: public DataSource getXADataSource() {
0299: return _xaDataSource;
0300: }
0301:
0302: /**
0303: * Sets the persistence.xml jta data source.
0304: */
0305: public void setJtaDataSource(DataSource dataSource) {
0306: _jtaDataSource = dataSource;
0307: }
0308:
0309: /**
0310: * Sets the persistence.xml non-jta data source.
0311: */
0312: public void setNonJtaDataSource(DataSource dataSource) {
0313: _nonJtaDataSource = dataSource;
0314: }
0315:
0316: /**
0317: * Return true for a jta-managed persistence unit
0318: */
0319: public boolean isJta() {
0320: return _nonJtaDataSource == null || _jtaDataSource != null;
0321: }
0322:
0323: /**
0324: * Returns the jdbc meta data.
0325: */
0326: public JdbcMetaData getMetaData() {
0327: if (_jdbcMetaData == null) {
0328: if (getDataSource() == null)
0329: throw new ConfigException(
0330: "No data-source specified for PersistenceUnit");
0331:
0332: _jdbcMetaData = JdbcMetaData.create(getDataSource());
0333: }
0334:
0335: return _jdbcMetaData;
0336: }
0337:
0338: /**
0339: * Set true if database tables should be created automatically.
0340: */
0341: public void setCreateDatabaseTables(boolean create) {
0342: _createDatabaseTables = create;
0343: }
0344:
0345: /**
0346: * Set true if database tables should be created automatically.
0347: */
0348: public boolean getCreateDatabaseTables() {
0349: return _createDatabaseTables;
0350: }
0351:
0352: /**
0353: * Set true if database tables should be validated automatically.
0354: */
0355: public void setValidateDatabaseTables(boolean validate) {
0356: _validateDatabaseTables = validate;
0357: }
0358:
0359: /**
0360: * Set true if database tables should be validated automatically.
0361: */
0362: public boolean getValidateDatabaseTables() {
0363: return _validateDatabaseTables;
0364: }
0365:
0366: /**
0367: * Set the default table cache time.
0368: */
0369: public void setTableCacheTimeout(long timeout) {
0370: _tableCacheTimeout = timeout;
0371: }
0372:
0373: /**
0374: * Get the default table cache time.
0375: */
0376: public long getTableCacheTimeout() {
0377: return _tableCacheTimeout;
0378: }
0379:
0380: /**
0381: * Set false for EJB-style generation.
0382: */
0383: public void setBytecodeGenerator(boolean isBytecodeGenerator) {
0384: if (isBytecodeGenerator)
0385: _generator = _amberContainer.getGenerator();
0386: else
0387: _generator = new AmberGeneratorImpl(this );
0388: }
0389:
0390: /**
0391: * Returns a new xid.
0392: */
0393: public long getXid() {
0394: synchronized (this ) {
0395: return _xid++;
0396: }
0397: }
0398:
0399: /**
0400: * Returns the enhanced loader.
0401: */
0402: public JClassLoader getJClassLoader() {
0403: return _amberContainer.getJClassLoader();
0404: }
0405:
0406: /**
0407: * Creates a table.
0408: */
0409: public Table createTable(String tableName) {
0410: if (log.isLoggable(Level.FINER))
0411: log.log(Level.FINER, "AmberPersistenceUnit.createTable: "
0412: + tableName);
0413:
0414: Table table = _tableMap.get(tableName);
0415:
0416: if (table == null) {
0417: table = new Table(this , tableName);
0418: table.setCacheTimeout(getTableCacheTimeout());
0419:
0420: _tableMap.put(tableName, table);
0421:
0422: _lazyTable.add(table);
0423: }
0424:
0425: return table;
0426: }
0427:
0428: public Throwable getConfigException() {
0429: return _amberContainer.getConfigException();
0430: }
0431:
0432: /**
0433: * Add an entity.
0434: *
0435: * @param className the class name
0436: * @param type the JClass type if it is already verified as an
0437: * Entity | Embeddable | MappedSuperclass
0438: */
0439: public void addEntityClass(String className, JClass type)
0440: throws ConfigException {
0441: if (type == null) {
0442: type = getJClassLoader().forName(className);
0443:
0444: if (type == null) {
0445: throw new ConfigException(L.l(
0446: "'{0}' is an unknown type", className));
0447: }
0448: }
0449:
0450: boolean isEntity = _entityIntrospector.isEntity(type);
0451: boolean isEmbeddable = _embeddableIntrospector
0452: .isEmbeddable(type);
0453: boolean isMappedSuper = _mappedSuperIntrospector
0454: .isMappedSuper(type);
0455:
0456: if (!(isEntity || isEmbeddable || isMappedSuper)) {
0457: throw new ConfigException(
0458: L
0459: .l(
0460: "'{0}' must implement javax.persistence.Entity, javax.persistence.Embeddable or javax.persistence.MappedSuperclass",
0461: className));
0462: }
0463:
0464: try {
0465: if (isEntity) {
0466: EntityType entityType = (EntityType) _entityIntrospector
0467: .introspect(type);
0468:
0469: // EntityType entity = createEntity(type);
0470:
0471: _amberContainer.addEntity(className, entityType);
0472: } else if (isEmbeddable) {
0473: EmbeddableType embeddableType = createEmbeddable(type);
0474:
0475: _amberContainer
0476: .addEmbeddable(className, embeddableType);
0477: } else if (isMappedSuper) {
0478: // XXX: needs to refactor EntityIntrospector and MappedSuperIntrospector.
0479: MappedSuperclassType mappedSuperclassType = (MappedSuperclassType) _entityIntrospector
0480: .introspect(type);
0481:
0482: _amberContainer.addMappedSuperclass(className,
0483: mappedSuperclassType);
0484: }
0485: } catch (Exception e) {
0486: _amberContainer.addEntityException(className, e);
0487:
0488: throw ConfigException.create(e);
0489: }
0490: }
0491:
0492: /**
0493: * Adds a sql result set mapping.
0494: */
0495: public void addSqlResultSetMapping(String resultSetName,
0496: SqlResultSetMappingConfig resultSet) throws ConfigException {
0497: if (_sqlResultSetMap.containsKey(resultSetName)) {
0498: throw new ConfigException(L.l(
0499: "SqlResultSetMapping '{0}' is already defined.",
0500: resultSetName));
0501: }
0502:
0503: _sqlResultSetMap.put(resultSetName, resultSet);
0504: }
0505:
0506: /**
0507: * Returns the sql result set mapping.
0508: */
0509: public SqlResultSetMappingConfig getSqlResultSetMapping(
0510: String resultSetName) {
0511: return _sqlResultSetMap.get(resultSetName);
0512: }
0513:
0514: /**
0515: * Adds a named query.
0516: */
0517: public void addNamedQuery(String name, String query)
0518: throws ConfigException {
0519: if (_namedQueryMap.containsKey(name)) {
0520: throw new ConfigException(L.l(
0521: "Named query '{0}': '{1}' is already defined.",
0522: name, query));
0523: }
0524:
0525: _namedQueryMap.put(name, query);
0526: }
0527:
0528: /**
0529: * Returns the named query statement.
0530: */
0531: public String getNamedQuery(String name) {
0532: return (String) _namedQueryMap.get(name);
0533: }
0534:
0535: /**
0536: * Adds a named native query.
0537: */
0538: public void addNamedNativeQuery(String name,
0539: NamedNativeQueryConfig queryConfig) throws ConfigException {
0540: if (_namedNativeQueryMap.containsKey(name)) {
0541: throw new ConfigException(L.l(
0542: "NamedNativeQuery '{0}' is already defined.", name));
0543: }
0544:
0545: _namedNativeQueryMap.put(name, queryConfig);
0546: }
0547:
0548: /**
0549: * Returns the named native query.
0550: */
0551: public NamedNativeQueryConfig getNamedNativeQuery(String name) {
0552: return _namedNativeQueryMap.get(name);
0553: }
0554:
0555: /**
0556: * Adds an entity.
0557: */
0558: public EntityType createEntity(JClass beanClass) {
0559: return createEntity(beanClass.getName(), beanClass);
0560: }
0561:
0562: /**
0563: * Adds an entity.
0564: */
0565: public EntityType createEntity(String name, JClass beanClass) {
0566: EntityType entityType = (EntityType) _typeManager.get(name);
0567:
0568: if (entityType != null)
0569: return entityType;
0570:
0571: // ejb/0al2
0572: // entityType = (EntityType) _typeManager.get(beanClass.getName());
0573:
0574: if (entityType == null) {
0575: // The parent type can be a @MappedSuperclass or an @EntityType.
0576: RelatedType parentType = null;
0577:
0578: for (JClass parentClass = beanClass.getSuperClass(); parentType == null
0579: && parentClass != null; parentClass = parentClass
0580: .getSuperClass()) {
0581: parentType = (RelatedType) _typeManager.get(parentClass
0582: .getName());
0583: }
0584:
0585: if (parentType != null)
0586: entityType = new SubEntityType(this , parentType);
0587: else
0588: entityType = new EntityType(this );
0589: }
0590:
0591: // _typeManager.put(name, entityType);
0592: _typeManager.put(name, entityType);
0593: // XXX: some confusion about the double entry
0594: if (_typeManager.get(beanClass.getName()) == null)
0595: _typeManager.put(beanClass.getName(), entityType);
0596:
0597: entityType.setName(name);
0598: entityType.setBeanClass(beanClass);
0599:
0600: _lazyConfigure.add(entityType);
0601: // getEnvManager().addLazyConfigure(entityType);
0602:
0603: AmberEntityHome entityHome = _entityHomeMap.get(beanClass
0604: .getName());
0605:
0606: if (entityHome == null) {
0607: entityHome = new AmberEntityHome(this , entityType);
0608: _lazyHomeInit.add(entityHome);
0609: _isInit = false;
0610: }
0611:
0612: addEntityHome(name, entityHome);
0613: // XXX: some confusion about the double entry, related to the EJB 3.0
0614: // confuction of named instances.
0615: addEntityHome(beanClass.getName(), entityHome);
0616:
0617: return entityType;
0618: }
0619:
0620: /**
0621: * Adds an entity.
0622: */
0623: public MappedSuperclassType createMappedSuperclass(String name,
0624: JClass beanClass) {
0625: MappedSuperclassType mappedSuperType = (MappedSuperclassType) _typeManager
0626: .get(name);
0627:
0628: if (mappedSuperType != null)
0629: return mappedSuperType;
0630:
0631: mappedSuperType = new MappedSuperclassType(this );
0632:
0633: _typeManager.put(name, mappedSuperType);
0634: // XXX: some confusion about the double entry
0635: if (_typeManager.get(beanClass.getName()) == null)
0636: _typeManager.put(beanClass.getName(), mappedSuperType);
0637:
0638: _mappedSuperclassTypes.add(mappedSuperType);
0639:
0640: mappedSuperType.setName(name);
0641: mappedSuperType.setBeanClass(beanClass);
0642:
0643: return mappedSuperType;
0644: }
0645:
0646: /**
0647: * Adds an embeddable type.
0648: */
0649: public EmbeddableType createEmbeddable(JClass beanClass) {
0650: return createEmbeddable(beanClass.getName(), beanClass);
0651: }
0652:
0653: /**
0654: * Adds an embeddable type.
0655: */
0656: public EmbeddableType createEmbeddable(String name, JClass beanClass) {
0657: Type type = _typeManager.get(name);
0658:
0659: if (type != null && !(type instanceof EmbeddableType))
0660: throw new ConfigException(L.l(
0661: "'{0}' is not a valid embeddable type", name));
0662:
0663: EmbeddableType embeddableType;
0664:
0665: embeddableType = (EmbeddableType) type;
0666:
0667: if (embeddableType != null)
0668: return embeddableType;
0669:
0670: embeddableType = new EmbeddableType(this );
0671:
0672: _typeManager.put(name, embeddableType);
0673:
0674: // XXX: some confusion about the double entry
0675: if (_typeManager.get(beanClass.getName()) == null)
0676: _typeManager.put(beanClass.getName(), embeddableType);
0677:
0678: embeddableType.setName(name);
0679: embeddableType.setBeanClass(beanClass);
0680:
0681: _embeddableTypes.add(embeddableType);
0682:
0683: try {
0684: getEmbeddableIntrospector().introspect(beanClass);
0685: } catch (RuntimeException e) {
0686: throw e;
0687: } catch (Exception e) {
0688: throw ConfigException.create(e);
0689: }
0690:
0691: return embeddableType;
0692: }
0693:
0694: /**
0695: * Adds an enumerated type.
0696: */
0697: public EnumType createEnum(String name, JClass beanClass) {
0698: EnumType enumType = (EnumType) _typeManager.get(name);
0699:
0700: if (enumType != null)
0701: return enumType;
0702:
0703: enumType = new EnumType();
0704:
0705: _typeManager.put(name, enumType);
0706:
0707: // XXX: some confusion about the double entry
0708: if (_typeManager.get(beanClass.getName()) == null)
0709: _typeManager.put(beanClass.getName(), enumType);
0710:
0711: enumType.setName(name);
0712: enumType.setBeanClass(beanClass);
0713:
0714: return enumType;
0715: }
0716:
0717: /**
0718: * Gets a default listener.
0719: */
0720: public ListenerType getDefaultListener(String className) {
0721: return _amberContainer.getDefaultListener(className);
0722: }
0723:
0724: /**
0725: * Adds a default listener.
0726: */
0727: public ListenerType addDefaultListener(JClass beanClass) {
0728: ListenerType listenerType = getListener(beanClass);
0729:
0730: if (!_defaultListeners.contains(listenerType)) {
0731: _defaultListeners.add(listenerType);
0732:
0733: _amberContainer.addDefaultListener(beanClass.getName(),
0734: listenerType);
0735: }
0736:
0737: return listenerType;
0738: }
0739:
0740: /**
0741: * Gets an entity listener.
0742: */
0743: public ListenerType getEntityListener(String className) {
0744: return _amberContainer.getEntityListener(className);
0745: }
0746:
0747: /**
0748: * Adds an entity listener.
0749: */
0750: public ListenerType addEntityListener(String entityName,
0751: JClass listenerClass) {
0752: ListenerType listenerType = getListener(listenerClass);
0753:
0754: _amberContainer.addEntityListener(entityName, listenerType);
0755:
0756: return listenerType;
0757: }
0758:
0759: private ListenerType getListener(JClass beanClass) {
0760: String name = beanClass.getName();
0761:
0762: ListenerType listenerType = (ListenerType) _typeManager
0763: .get(name);
0764:
0765: if (listenerType != null)
0766: return listenerType;
0767:
0768: listenerType = new ListenerType(this );
0769:
0770: ListenerType parentType = null;
0771:
0772: for (JClass parentClass = beanClass.getSuperClass(); parentType == null
0773: && parentClass != null; parentClass = parentClass
0774: .getSuperClass()) {
0775: parentType = (ListenerType) _typeManager.get(parentClass
0776: .getName());
0777: }
0778:
0779: if (parentType != null)
0780: listenerType = new SubListenerType(this , parentType);
0781: else
0782: listenerType = new ListenerType(this );
0783:
0784: _typeManager.put(name, listenerType);
0785:
0786: listenerType.setName(name);
0787: listenerType.setBeanClass(beanClass);
0788:
0789: return listenerType;
0790: }
0791:
0792: /**
0793: * Adds a new home bean.
0794: */
0795: private void addEntityHome(String name, AmberEntityHome home) {
0796: _entityHomeMap.put(name, home);
0797:
0798: // getEnvManager().addEntityHome(name, home);
0799: }
0800:
0801: /**
0802: * Returns a table generator.
0803: */
0804: public IdGenerator getTableGenerator(String name) {
0805: return _tableGenMap.get(name);
0806: }
0807:
0808: /**
0809: * Sets a table generator.
0810: */
0811: public IdGenerator putTableGenerator(String name, IdGenerator gen) {
0812: synchronized (_tableGenMap) {
0813: IdGenerator oldGen = _tableGenMap.get(name);
0814:
0815: if (oldGen != null)
0816: return oldGen;
0817: else {
0818: _tableGenMap.put(name, gen);
0819: return gen;
0820: }
0821: }
0822: }
0823:
0824: /**
0825: * Adds a generator table.
0826: */
0827: public GeneratorTableType createGeneratorTable(String name) {
0828: Type type = _typeManager.get(name);
0829:
0830: if (type instanceof GeneratorTableType)
0831: return (GeneratorTableType) type;
0832:
0833: if (type != null)
0834: throw new RuntimeException(L.l(
0835: "'{0}' is a duplicate generator table.", type));
0836:
0837: GeneratorTableType genType = new GeneratorTableType(this , name);
0838:
0839: _typeManager.put(name, genType);
0840:
0841: // _lazyGenerate.add(genType);
0842:
0843: return genType;
0844: }
0845:
0846: /**
0847: * Returns a sequence generator.
0848: */
0849: public SequenceIdGenerator createSequenceGenerator(String name,
0850: int size) throws ConfigException {
0851: synchronized (_sequenceGenMap) {
0852: SequenceIdGenerator gen = _sequenceGenMap.get(name);
0853:
0854: if (gen == null) {
0855: gen = new SequenceIdGenerator(this , name, size);
0856:
0857: _sequenceGenMap.put(name, gen);
0858: }
0859:
0860: return gen;
0861: }
0862: }
0863:
0864: /**
0865: * Configures a type.
0866: */
0867: public void initType(AbstractEnhancedType type) throws Exception {
0868: type.init();
0869:
0870: getGenerator().generate(type);
0871: }
0872:
0873: /**
0874: * Configure lazy.
0875: */
0876: public void generate() throws Exception {
0877: configure();
0878:
0879: AbstractEnhancedType type = null;
0880:
0881: try {
0882: for (MappedSuperclassType mappedType : _mappedSuperclassTypes) {
0883: type = mappedType;
0884:
0885: initType(mappedType);
0886: }
0887:
0888: while (_lazyGenerate.size() > 0) {
0889: EntityType entityType = _lazyGenerate.remove(0);
0890:
0891: type = entityType;
0892:
0893: // Entity
0894: initType(entityType);
0895:
0896: ArrayList<ListenerType> listeners;
0897:
0898: String className = entityType.getBeanClass().getName();
0899:
0900: listeners = _amberContainer
0901: .getEntityListeners(className);
0902:
0903: if (listeners == null)
0904: continue;
0905:
0906: // Entity Listeners
0907: for (ListenerType listenerType : listeners) {
0908: type = listenerType;
0909:
0910: initType(listenerType);
0911: }
0912: }
0913:
0914: // Embeddable
0915: for (EmbeddableType embeddableType : _embeddableTypes) {
0916: type = embeddableType;
0917:
0918: initType(embeddableType);
0919: }
0920:
0921: // Default Listeners
0922: for (ListenerType listenerType : _defaultListeners) {
0923: type = listenerType;
0924:
0925: initType(listenerType);
0926: }
0927: } catch (Exception e) {
0928: if (type != null) {
0929: type.setConfigException(e);
0930:
0931: _amberContainer.addEntityException(type.getBeanClass()
0932: .getName(), e);
0933: }
0934:
0935: throw e;
0936: }
0937:
0938: try {
0939: getGenerator().compile();
0940: } catch (Exception e) {
0941: _amberContainer.addException(e);
0942:
0943: throw e;
0944: }
0945: }
0946:
0947: /**
0948: * Gets the JPA flag.
0949: */
0950: public boolean isJPA() {
0951: return _isJPA;
0952: }
0953:
0954: /**
0955: * Sets the JPA flag.
0956: */
0957: public void setJPA(boolean isJPA) {
0958: _isJPA = isJPA;
0959: }
0960:
0961: /**
0962: * Configure lazy.
0963: */
0964: public void generate(JavaClassGenerator javaGen) throws Exception {
0965: configure();
0966:
0967: while (_lazyGenerate.size() > 0) {
0968: EntityType type = _lazyGenerate.remove(0);
0969:
0970: type.init();
0971:
0972: if (type instanceof EntityType) {
0973: EntityType entityType = (EntityType) type;
0974:
0975: if (!entityType.isGenerated()) {
0976: if (entityType.getInstanceClassName() == null)
0977: throw new ConfigException(
0978: L
0979: .l(
0980: "'{0}' does not have a configured instance class.",
0981: entityType));
0982:
0983: entityType.setGenerated(true);
0984:
0985: try {
0986: getGenerator()
0987: .generateJava(javaGen, entityType);
0988: } catch (Exception e) {
0989: log.log(Level.FINER, e.toString(), e);
0990: }
0991: }
0992: }
0993:
0994: configure();
0995: }
0996:
0997: for (EmbeddableType embeddableType : _embeddableTypes) {
0998:
0999: embeddableType.init();
1000:
1001: if (!embeddableType.isGenerated()) {
1002: if (embeddableType.getInstanceClassName() == null)
1003: throw new ConfigException(
1004: L
1005: .l(
1006: "'{0}' does not have a configured instance class.",
1007: embeddableType));
1008:
1009: embeddableType.setGenerated(true);
1010:
1011: try {
1012: getGenerator()
1013: .generateJava(javaGen, embeddableType);
1014: } catch (Exception e) {
1015: log.log(Level.FINER, e.toString(), e);
1016: }
1017: }
1018: }
1019:
1020: for (SequenceIdGenerator gen : _sequenceGenMap.values())
1021: gen.init(this );
1022:
1023: while (_defaultListeners.size() > 0) {
1024: ListenerType type = _defaultListeners.remove(0);
1025:
1026: type.init();
1027:
1028: if (!type.isGenerated()) {
1029: if (type.getInstanceClassName() == null)
1030: throw new ConfigException(
1031: L
1032: .l(
1033: "'{0}' does not have a configured instance class.",
1034: type));
1035:
1036: type.setGenerated(true);
1037:
1038: try {
1039: getGenerator().generateJava(javaGen, type);
1040: } catch (Exception e) {
1041: log.log(Level.FINER, e.toString(), e);
1042: }
1043: }
1044: }
1045: }
1046:
1047: /**
1048: * Returns the @Embeddable introspector.
1049: */
1050: public EmbeddableIntrospector getEmbeddableIntrospector() {
1051: return _embeddableIntrospector;
1052: }
1053:
1054: /**
1055: * Configure lazy.
1056: */
1057: public void configure() throws Exception {
1058: _embeddableIntrospector.configure();
1059: _mappedSuperIntrospector.configure();
1060:
1061: _entityIntrospector.configure();
1062:
1063: while (_lazyConfigure.size() > 0) {
1064: EntityType type = _lazyConfigure.remove(0);
1065:
1066: if (type.startConfigure()) {
1067: // getEnvManager().getGenerator().configure(type);
1068: }
1069:
1070: _entityIntrospector.configure();
1071:
1072: if (!_lazyGenerate.contains(type))
1073: _lazyGenerate.add(type);
1074: }
1075:
1076: updateFlushPriority();
1077: }
1078:
1079: /**
1080: * Returns the entity home.
1081: */
1082: public AmberEntityHome getEntityHome(String name) {
1083: if (!_isInit) {
1084: try {
1085: initEntityHomes();
1086: } catch (RuntimeException e) {
1087: throw e;
1088: } catch (Exception e) {
1089: throw new AmberRuntimeException(e);
1090: }
1091: }
1092:
1093: return _entityHomeMap.get(name);
1094: }
1095:
1096: /**
1097: * Returns the entity home by the schema name.
1098: */
1099: public AmberEntityHome getHomeBySchema(String name) {
1100: for (AmberEntityHome home : _entityHomeMap.values()) {
1101: if (name.equals(home.getEntityType().getName()))
1102: return home;
1103: }
1104:
1105: try {
1106: createType(name);
1107: } catch (Exception e) {
1108: }
1109:
1110: return _entityHomeMap.get(name);
1111: }
1112:
1113: /**
1114: * Returns a matching embeddable type.
1115: */
1116: public EmbeddableType getEmbeddable(String className) {
1117: Type type = _typeManager.get(className);
1118:
1119: if (type instanceof EmbeddableType)
1120: return (EmbeddableType) type;
1121: else
1122: return null;
1123: }
1124:
1125: /**
1126: * Returns a matching entity.
1127: */
1128: public EntityType getEntityType(String className) {
1129: Type type = _typeManager.get(className);
1130:
1131: if (type instanceof EntityType)
1132: return (EntityType) type;
1133: else
1134: return null;
1135: }
1136:
1137: /**
1138: * Returns a matching mapped superclass.
1139: */
1140: public MappedSuperclassType getMappedSuperclass(String className) {
1141: Type type = _typeManager.get(className);
1142:
1143: if (type instanceof MappedSuperclassType)
1144: return (MappedSuperclassType) type;
1145:
1146: return null;
1147: }
1148:
1149: /**
1150: * Returns a matching entity.
1151: */
1152: public EntityType getEntityByInstanceClass(String className) {
1153: return _typeManager.getEntityByInstanceClass(className);
1154: }
1155:
1156: /**
1157: * Updates global entity priorities for flushing.
1158: */
1159: public void updateFlushPriority() {
1160: ArrayList<EntityType> updatingEntities = new ArrayList<EntityType>();
1161:
1162: try {
1163: HashMap<String, Type> typeMap = _typeManager.getTypeMap();
1164:
1165: Collection<Type> types = typeMap.values();
1166:
1167: Iterator it = types.iterator();
1168:
1169: while (it.hasNext()) {
1170: Type type = (Type) it.next();
1171:
1172: if (type instanceof EntityType) {
1173: EntityType entityType = (EntityType) type;
1174:
1175: if (updatingEntities.contains(entityType))
1176: continue;
1177:
1178: updatingEntities.add(entityType);
1179:
1180: entityType.updateFlushPriority(updatingEntities);
1181: }
1182: }
1183: } finally {
1184: updatingEntities = null;
1185: }
1186: }
1187:
1188: /**
1189: * Creates a type.
1190: */
1191: public Type createType(String typeName) throws ConfigException {
1192: Type type = _typeManager.get(typeName);
1193:
1194: if (type != null)
1195: return type;
1196:
1197: JClass cl = _amberContainer.getJClassLoader().forName(typeName);
1198:
1199: if (cl == null)
1200: throw new ConfigException(L.l("'{0}' is an unknown type",
1201: typeName));
1202:
1203: return createType(cl);
1204: }
1205:
1206: /**
1207: * Creates a type.
1208: */
1209: public Type createType(JClass javaType) throws ConfigException {
1210: Type type = _typeManager.create(javaType);
1211:
1212: if (type != null)
1213: return type;
1214:
1215: return createEntity(javaType);
1216: }
1217:
1218: /**
1219: * Sets the generator.
1220: */
1221: public AmberGenerator getGenerator() {
1222: if (_generator != null)
1223: return _generator;
1224: /*
1225: else if (_enhancer != null)
1226: return _enhancer;
1227: */
1228: else {
1229: _generator = _amberContainer.getGenerator();
1230:
1231: return _generator;
1232: }
1233: }
1234:
1235: /**
1236: * Returns the FALSE SQL literal, i.e., either "false" or "0".
1237: */
1238: public String getFalseLiteral() {
1239: return getMetaData().getFalseLiteral();
1240: }
1241:
1242: /**
1243: * Returns true if POSITION SQL function is allowed.
1244: */
1245: public boolean hasPositionFunction() {
1246: return getMetaData().supportsPositionFunction();
1247: }
1248:
1249: /**
1250: * Returns true if generated keys are allowed.
1251: */
1252: public boolean hasReturnGeneratedKeys() {
1253: return getMetaData().supportsGetGeneratedKeys();
1254: }
1255:
1256: /**
1257: * Sets the entity mappings config.
1258: */
1259: public void setEntityMappingsList(
1260: ArrayList<EntityMappingsConfig> entityMappingsList) {
1261: _entityMappingsList = entityMappingsList;
1262:
1263: _entityIntrospector.setEntityMappingsList(_entityMappingsList);
1264:
1265: _mappedSuperIntrospector
1266: .setEntityMappingsList(_entityMappingsList);
1267: }
1268:
1269: /**
1270: * Initialize the resource.
1271: */
1272: public void init() throws ConfigException, IOException {
1273: initLoaders();
1274:
1275: if (_entityMappingsList != null) {
1276: BaseConfigIntrospector introspector = new BaseConfigIntrospector();
1277:
1278: introspector.initMetaData(_entityMappingsList, this );
1279: }
1280:
1281: if (_dataSource == null)
1282: return;
1283:
1284: /*
1285: try {
1286: Connection conn = _dataSource.getConnection();
1287:
1288: try {
1289: DatabaseMetaData metaData = conn.getMetaData();
1290:
1291: try {
1292: _supportsGetGeneratedKeys = metaData.supportsGetGeneratedKeys();
1293: } catch (Throwable e) {
1294: }
1295: } finally {
1296: conn.close();
1297: }
1298: } catch (SQLException e) {
1299: throw new ConfigException(e);
1300: }
1301: */
1302: }
1303:
1304: /**
1305: * Initialize the resource.
1306: */
1307: public void initLoaders() throws ConfigException, IOException {
1308: // getEnvManager().initLoaders();
1309: }
1310:
1311: public void initEntityHomes() throws AmberRuntimeException,
1312: ConfigException {
1313: synchronized (this ) {
1314: if (_isInit)
1315: return;
1316: _isInit = true;
1317: }
1318:
1319: initTables();
1320:
1321: while (_lazyHomeInit.size() > 0) {
1322: AmberEntityHome home = _lazyHomeInit.remove(0);
1323:
1324: home.init();
1325: }
1326: }
1327:
1328: /**
1329: * Configure lazy.
1330: */
1331: public void initTables() throws ConfigException {
1332: while (_lazyTable.size() > 0) {
1333: Table table = _lazyTable.remove(0);
1334:
1335: if (getDataSource() == null)
1336: throw new ConfigException(L.l(
1337: "{0}: No configured data-source found.", this ));
1338:
1339: if (getCreateDatabaseTables())
1340: table.createDatabaseTable(this );
1341:
1342: if (getValidateDatabaseTables())
1343: table.validateDatabaseTable(this );
1344: }
1345: }
1346:
1347: /**
1348: * Returns the cache connection.
1349: */
1350: public CacheConnection getCacheConnection() {
1351: // cache connection cannot be reused (#998)
1352:
1353: CacheConnection cacheConnection = new CacheConnection(this );
1354:
1355: // ejb/0a0b - avoid dangling connections.
1356: cacheConnection.register();
1357:
1358: return cacheConnection;
1359: }
1360:
1361: /**
1362: * Returns the cache connection.
1363: */
1364: public AmberConnection createAmberConnection(boolean isExtended) {
1365: return new AmberConnection(this , isExtended);
1366: }
1367:
1368: /**
1369: * Returns the thread's amber connection.
1370: */
1371: public AmberConnection getThreadConnection(boolean isExtended) {
1372: AmberConnection aConn = _threadConnection.get();
1373:
1374: if (aConn == null) {
1375: aConn = new AmberConnection(this , isExtended);
1376: aConn.initThreadConnection();
1377:
1378: _threadConnection.set(aConn);
1379: }
1380:
1381: return aConn;
1382: }
1383:
1384: /**
1385: * Unset the thread's amber connection.
1386: */
1387: public void removeThreadConnection() {
1388: _threadConnection.set(null);
1389: }
1390:
1391: /**
1392: * Returns an EntityHome.
1393: */
1394: public AmberEntityHome getHome(Class cl) {
1395: return getEntityHome(cl.getName());
1396: }
1397:
1398: /**
1399: * Returns the query cache.
1400: */
1401: public AbstractQuery getQueryParseCache(String sql) {
1402: return _queryParseCache.get(sql);
1403: }
1404:
1405: /**
1406: * Returns the query cache.
1407: */
1408: public void putQueryParseCache(String sql, AbstractQuery query) {
1409: _queryParseCache.put(sql, query);
1410: }
1411:
1412: /**
1413: * Returns the query result.
1414: */
1415: public ResultSetCacheChunk getQueryChunk(QueryCacheKey key) {
1416: SoftReference<ResultSetCacheChunk> ref = _queryCache.get(key);
1417:
1418: if (ref == null)
1419: return null;
1420: else {
1421: ResultSetCacheChunk chunk = ref.get();
1422:
1423: if (chunk != null && chunk.isValid())
1424: return chunk;
1425: else
1426: return null;
1427: }
1428: }
1429:
1430: /**
1431: * Returns the query meta data.
1432: */
1433: public ResultSetMetaData getQueryMetaData(QueryCacheKey key) {
1434: SoftReference<ResultSetMetaData> ref = _queryCacheMetaData
1435: .get(key);
1436:
1437: if (ref == null)
1438: return null;
1439: else
1440: return ref.get();
1441: }
1442:
1443: /**
1444: * Applies persistence unit default and entity listeners
1445: * for @PreXxx, @PostXxx callbacks.
1446: */
1447: protected void callListeners(int callbackIndex, Entity entity) {
1448: // ejb/0g22
1449: if (!isJPA())
1450: return;
1451:
1452: String className = entity.getClass().getName();
1453:
1454: EntityType entityType = (EntityType) _typeManager
1455: .get(className);
1456:
1457: if (!entityType.getExcludeDefaultListeners()) {
1458: for (ListenerType listenerType : _defaultListeners) {
1459: for (JMethod m : listenerType
1460: .getCallbacks(callbackIndex)) {
1461: Listener listener = (Listener) listenerType
1462: .getInstance();
1463: listener.__caucho_callback(callbackIndex, entity);
1464: }
1465: }
1466: }
1467:
1468: ArrayList<ListenerType> listeners;
1469:
1470: listeners = _amberContainer.getEntityListeners(className);
1471:
1472: if (listeners == null)
1473: return;
1474:
1475: for (ListenerType listenerType : listeners) {
1476:
1477: if ((!entityType.getExcludeDefaultListeners())
1478: && _defaultListeners.contains(listenerType))
1479: continue;
1480:
1481: for (JMethod m : listenerType.getCallbacks(callbackIndex)) {
1482: Listener listener = (Listener) listenerType
1483: .getInstance();
1484: listener.__caucho_callback(callbackIndex, entity);
1485: }
1486: }
1487: }
1488:
1489: /**
1490: * Sets the query result.
1491: */
1492: public void putQueryChunk(QueryCacheKey key,
1493: ResultSetCacheChunk chunk) {
1494: _queryCache.put(key, new SoftReference<ResultSetCacheChunk>(
1495: chunk));
1496: }
1497:
1498: /**
1499: * Sets the query meta data.
1500: */
1501: public void putQueryMetaData(QueryCacheKey key,
1502: ResultSetMetaData metaData) {
1503: _queryCacheMetaData.put(key,
1504: new SoftReference<ResultSetMetaData>(metaData));
1505: }
1506:
1507: /**
1508: * Returns the entity item.
1509: */
1510: public EntityItem getEntityItem(String homeName, Object key)
1511: throws AmberException {
1512: AmberEntityHome home = getEntityHome(homeName);
1513:
1514: // XXX: needs refactoring
1515: throw new IllegalStateException("XXXX:");
1516:
1517: // return home.findEntityItem(getCacheConnection(), key, false);
1518: }
1519:
1520: /**
1521: * Returns the entity with the given key.
1522: */
1523: public EntityItem getEntity(EntityType rootType, Object key) {
1524: SoftReference<EntityItem> ref;
1525:
1526: synchronized (_entityKey) {
1527: _entityKey.init(rootType.getInstanceClass(), key);
1528: ref = _entityCache.get(_entityKey);
1529: }
1530:
1531: if (ref != null)
1532: return ref.get();
1533: else
1534: return null;
1535: }
1536:
1537: /**
1538: * Returns the entity with the given key.
1539: */
1540: public EntityItem getEntity(EntityKey entityKey) {
1541: SoftReference<EntityItem> ref;
1542:
1543: ref = _entityCache.get(entityKey);
1544:
1545: if (ref != null)
1546: return ref.get();
1547: else
1548: return null;
1549: }
1550:
1551: /**
1552: * Sets the entity result.
1553: */
1554: public EntityItem putEntity(EntityType rootType, Object key,
1555: EntityItem entity) {
1556: if (entity == null)
1557: throw new IllegalStateException(
1558: L
1559: .l("Null entity item cannot be added to the persistence unit cache"));
1560:
1561: SoftReference<EntityItem> ref = new SoftReference<EntityItem>(
1562: entity);
1563: EntityKey entityKey = new EntityKey(
1564: rootType.getInstanceClass(), key);
1565:
1566: // can't use putIfNew because the SoftReference might be empty, i.e.
1567: // not "new" but in need of replacement
1568: ref = _entityCache.put(entityKey, ref);
1569:
1570: return entity;
1571: }
1572:
1573: /**
1574: * Sets the entity result.
1575: */
1576: public EntityItem putEntity(Class cl, Object key, EntityItem entity) {
1577: if (entity == null)
1578: throw new IllegalStateException(
1579: L
1580: .l("Null entity item cannot be added to the persistence unit cache"));
1581:
1582: SoftReference<EntityItem> ref = new SoftReference<EntityItem>(
1583: entity);
1584: EntityKey entityKey = new EntityKey(cl, key);
1585:
1586: // can't use putIfNew because the SoftReference might be empty, i.e.
1587: // not "new" but in need of replacement
1588: ref = _entityCache.put(entityKey, ref);
1589:
1590: return entity;
1591: }
1592:
1593: /**
1594: * Remove the entity result.
1595: */
1596: public EntityItem removeEntity(EntityType rootType, Object key) {
1597: SoftReference<EntityItem> ref;
1598:
1599: synchronized (_entityKey) {
1600: _entityKey.init(rootType.getInstanceClass(), key);
1601: ref = _entityCache.remove(_entityKey);
1602: }
1603:
1604: if (ref != null)
1605: return ref.get();
1606: else
1607: return null;
1608: }
1609:
1610: /**
1611: * Updates the cache item after commit.
1612: */
1613: public EntityItem updateCacheItem(EntityType rootType, Object key,
1614: Entity contextEntity, EntityItem cacheItem) {
1615: if (cacheItem == null)
1616: throw new IllegalStateException(
1617: L
1618: .l("Null entity item cannot be used to update the persistence unit cache"));
1619:
1620: SoftReference<EntityItem> ref;
1621:
1622: synchronized (_entityKey) {
1623: _entityKey.init(rootType.getInstanceClass(), key);
1624: ref = _entityCache.get(_entityKey);
1625:
1626: EntityItem oldCacheItem = null;
1627:
1628: // jpa/0g70
1629: if (ref != null)
1630: oldCacheItem = ref.get();
1631:
1632: // jpa/0q00
1633: if (oldCacheItem == null) {
1634: ref = new SoftReference<EntityItem>(cacheItem);
1635: EntityKey entityKey = new EntityKey(rootType
1636: .getInstanceClass(), key);
1637:
1638: // ejb/0628, ejb/06d0
1639: ref = _entityCache.putIfNew(entityKey, ref);
1640:
1641: oldCacheItem = ref.get();
1642: }
1643:
1644: if (oldCacheItem != null)
1645: cacheItem = oldCacheItem;
1646:
1647: contextEntity.__caucho_updateCacheItem(cacheItem
1648: .getEntity());
1649: }
1650:
1651: return cacheItem;
1652: }
1653:
1654: /**
1655: * Safely copies a cache item to a context object.
1656: */
1657: public Entity copyFromCacheItem(AmberConnection aConn,
1658: Entity contextEntity, EntityItem cacheItem) {
1659: if (cacheItem == null)
1660: throw new IllegalStateException(
1661: L
1662: .l("Null cache item cannot be used to update a persistence context object"));
1663:
1664: synchronized (_entityKey) {
1665: cacheItem.copyTo(contextEntity, aConn);
1666: }
1667:
1668: return contextEntity;
1669: }
1670:
1671: /**
1672: * Completions affecting the cache.
1673: */
1674: public void complete(ArrayList<AmberCompletion> completions) {
1675: int size = completions.size();
1676: if (size == 0)
1677: return;
1678:
1679: synchronized (_entityCache) {
1680: Iterator<LruCache.Entry<EntityKey, SoftReference<EntityItem>>> iter;
1681:
1682: iter = _entityCache.iterator();
1683: while (iter.hasNext()) {
1684: LruCache.Entry<EntityKey, SoftReference<EntityItem>> entry;
1685: entry = iter.next();
1686:
1687: EntityKey key = entry.getKey();
1688: SoftReference<EntityItem> valueRef = entry.getValue();
1689: EntityItem value = valueRef.get();
1690:
1691: if (value == null)
1692: continue;
1693:
1694: AmberEntityHome entityHome = value.getEntityHome();
1695: EntityType entityRoot = entityHome.getEntityType();
1696: Object entityKey = key.getKey();
1697:
1698: for (int i = 0; i < size; i++) {
1699: if (completions.get(i).complete(entityRoot,
1700: entityKey, value)) {
1701: // XXX: delete
1702: }
1703: }
1704: }
1705: }
1706:
1707: synchronized (_queryCache) {
1708: Iterator<SoftReference<ResultSetCacheChunk>> iter;
1709:
1710: iter = _queryCache.values();
1711: while (iter.hasNext()) {
1712: SoftReference<ResultSetCacheChunk> ref = iter.next();
1713:
1714: ResultSetCacheChunk chunk = ref.get();
1715:
1716: if (chunk != null) {
1717: for (int i = 0; i < size; i++) {
1718: if (completions.get(i).complete(chunk)) {
1719: // XXX: delete
1720: }
1721: }
1722: }
1723: }
1724: }
1725: }
1726:
1727: /**
1728: * destroys the manager.
1729: */
1730: public void destroy() {
1731: _typeManager = null;
1732: _queryCache = null;
1733: _entityCache = null;
1734: }
1735:
1736: /**
1737: * New Version of getCreateTableSQL which returns
1738: * the SQL for the table with the given SQL type
1739: * but takes sqlType, length, precision, and scale.
1740: */
1741: public String getCreateColumnSQL(int sqlType, int length,
1742: int precision, int scale) {
1743: return getMetaData().getCreateColumnSQL(sqlType, length,
1744: precision, scale);
1745: }
1746:
1747: public String toString() {
1748: return "AmberPersistenceUnit[" + _name + "]";
1749: }
1750: }
|