Source Code Cross Referenced for AmberConnection.java in  » EJB-Server-resin-3.1.5 » resin » com » caucho » amber » manager » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » EJB Server resin 3.1.5 » resin » com.caucho.amber.manager 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.AmberObjectNotFoundException;
0034:        import com.caucho.amber.AmberQuery;
0035:        import com.caucho.amber.AmberRuntimeException;
0036:        import com.caucho.amber.cfg.EntityResultConfig;
0037:        import com.caucho.amber.cfg.NamedNativeQueryConfig;
0038:        import com.caucho.amber.cfg.SqlResultSetMappingConfig;
0039:        import com.caucho.amber.collection.AmberCollection;
0040:        import com.caucho.amber.entity.*;
0041:        import com.caucho.amber.query.AbstractQuery;
0042:        import com.caucho.amber.query.QueryCacheKey;
0043:        import com.caucho.amber.query.QueryParser;
0044:        import com.caucho.amber.query.ResultSetCacheChunk;
0045:        import com.caucho.amber.query.UserQuery;
0046:        import com.caucho.amber.table.Table;
0047:        import com.caucho.amber.type.EntityType;
0048:        import com.caucho.config.ConfigException;
0049:        import com.caucho.ejb.EJBExceptionWrapper;
0050:        import com.caucho.jca.BeginResource;
0051:        import com.caucho.jca.CloseResource;
0052:        import com.caucho.jca.UserTransactionProxy;
0053:        import com.caucho.jdbc.JdbcMetaData;
0054:        import com.caucho.util.L10N;
0055:        import com.caucho.util.LruCache;
0056:
0057:        import javax.persistence.EntityExistsException;
0058:        import javax.persistence.EntityNotFoundException;
0059:        import javax.persistence.EntityTransaction;
0060:        import javax.persistence.FlushModeType;
0061:        import javax.persistence.LockModeType;
0062:        import javax.persistence.Query;
0063:        import javax.persistence.PersistenceException;
0064:        import javax.persistence.RollbackException;
0065:        import javax.persistence.TransactionRequiredException;
0066:        import javax.sql.DataSource;
0067:        import javax.transaction.Status;
0068:        import javax.transaction.Synchronization;
0069:        import javax.transaction.Transaction;
0070:        import java.lang.reflect.Method;
0071:        import java.sql.Connection;
0072:        import java.sql.PreparedStatement;
0073:        import java.sql.ResultSet;
0074:        import java.sql.ResultSetMetaData;
0075:        import java.sql.SQLException;
0076:        import java.sql.Statement;
0077:        import java.util.ArrayList;
0078:        import java.util.List;
0079:        import java.util.Map;
0080:        import java.util.logging.Level;
0081:        import java.util.logging.Logger;
0082:
0083:        /**
0084:         * The entity manager from a entity manager proxy.
0085:         */
0086:        public class AmberConnection implements  BeginResource, CloseResource,
0087:                Synchronization {
0088:            private static final L10N L = new L10N(AmberConnection.class);
0089:            private static final Logger log = Logger
0090:                    .getLogger(AmberConnection.class.getName());
0091:
0092:            private static final Entity[] NULL_ENTITIES = new Entity[0];
0093:
0094:            private AmberPersistenceUnit _persistenceUnit;
0095:
0096:            private boolean _isRegistered;
0097:            private boolean _isThreadConnection;
0098:
0099:            private Entity[] _entities = new Entity[32];
0100:            private int _entitiesTop;
0101:
0102:            private Entity[] _txEntities = NULL_ENTITIES;
0103:            private int _txEntitiesTop;
0104:
0105:            private ArrayList<AmberCompletion> _completionList = new ArrayList<AmberCompletion>();
0106:
0107:            private ArrayList<AmberCollection> _queries = new ArrayList<AmberCollection>();
0108:
0109:            private EntityTransaction _trans;
0110:
0111:            private long _xid;
0112:            private boolean _isInTransaction;
0113:            private boolean _isXA;
0114:
0115:            private boolean _isExtended;
0116:
0117:            private boolean _isAppManaged;
0118:
0119:            private Connection _conn;
0120:            private Connection _readConn;
0121:
0122:            private boolean _isAutoCommit = true;
0123:
0124:            private int _depth;
0125:
0126:            private LruCache<String, PreparedStatement> _preparedStatementMap = new LruCache<String, PreparedStatement>(
0127:                    32);
0128:
0129:            private ArrayList<Statement> _statements = new ArrayList<Statement>();
0130:
0131:            private EntityKey _entityKey = new EntityKey();
0132:            private QueryCacheKey _queryKey = new QueryCacheKey();
0133:
0134:            private ArrayList<Entity> _mergingEntities = new ArrayList<Entity>();
0135:
0136:            private boolean _isFlushAllowed = true;
0137:
0138:            /**
0139:             * Creates a manager instance.
0140:             */
0141:            AmberConnection(AmberPersistenceUnit persistenceUnit,
0142:                    boolean isExtended, boolean isAppManaged) {
0143:                _persistenceUnit = persistenceUnit;
0144:                _isExtended = isExtended;
0145:                _isAppManaged = isAppManaged;
0146:            }
0147:
0148:            /**
0149:             * Creates a manager instance.
0150:             */
0151:            AmberConnection(AmberPersistenceUnit persistenceUnit,
0152:                    boolean isExtended) {
0153:                this (persistenceUnit, isExtended, false);
0154:            }
0155:
0156:            /**
0157:             * Returns the persistence unit.
0158:             */
0159:            public AmberPersistenceUnit getPersistenceUnit() {
0160:                return _persistenceUnit;
0161:            }
0162:
0163:            /**
0164:             * Returns true for JPA.
0165:             */
0166:            public boolean isJPA() {
0167:                return _persistenceUnit.isJPA();
0168:            }
0169:
0170:            /**
0171:             * Set true for a threaded connection.
0172:             */
0173:            public void initThreadConnection() {
0174:                _isThreadConnection = true;
0175:
0176:                initJta();
0177:            }
0178:
0179:            public void initJta() {
0180:                // non-jta connections do not register with the local transaction
0181:                if (_persistenceUnit.isJta())
0182:                    register();
0183:            }
0184:
0185:            /**
0186:             * Makes the instance managed.
0187:             */
0188:            public void persist(Object entityObject) {
0189:                RuntimeException exn = null;
0190:
0191:                try {
0192:                    if (entityObject == null)
0193:                        return;
0194:
0195:                    Entity entity = checkEntityType(entityObject, "persist");
0196:
0197:                    checkTransactionRequired("persist");
0198:
0199:                    persistInternal(entity);
0200:
0201:                    // XXX: check spec. for JTA vs. non-JTA behavior and add QA.
0202:                    // ejb30/persistence/ee/packaging/ejb/resource_local/test14
0203:                    if (!_persistenceUnit.isJta())
0204:                        flushInternal();
0205:                } catch (RuntimeException e) {
0206:                    exn = e;
0207:                } catch (SQLException e) {
0208:                    exn = new IllegalStateException(e);
0209:                } catch (Exception e) {
0210:                    exn = new EJBExceptionWrapper(e);
0211:                }
0212:
0213:                if (exn != null) {
0214:                    if (!_persistenceUnit.isJta()) {
0215:                        if (_trans != null)
0216:                            _trans.setRollbackOnly();
0217:                    }
0218:
0219:                    throw exn;
0220:                }
0221:            }
0222:
0223:            /**
0224:             * Makes the instance managed called
0225:             * from cascading operations.
0226:             */
0227:            public void persistFromCascade(Object o) {
0228:                // jpa/0h25, jpa/0i5e
0229:
0230:                try {
0231:                    if (o == null)
0232:                        return;
0233:
0234:                    Entity entity = (Entity) o;
0235:
0236:                    // jpa/0h25
0237:
0238:                    persistInternal(entity);
0239:
0240:                } catch (EntityExistsException e) {
0241:                    log.log(Level.FINER, e.toString(), e);
0242:                    // This is not an issue. It is the cascading
0243:                    // operation trying to persist the source
0244:                    // entity from the destination end.
0245:                } catch (RuntimeException e) {
0246:                    throw e;
0247:                } catch (SQLException e) {
0248:                    throw new IllegalStateException(e);
0249:                } catch (Exception e) {
0250:                    throw new EJBExceptionWrapper(e);
0251:                }
0252:            }
0253:
0254:            /**
0255:             * Merges the state of the entity into the current context.
0256:             */
0257:            public <T> T merge(T entityT) {
0258:                RuntimeException exn = null;
0259:
0260:                try {
0261:                    flushInternal();
0262:
0263:                    // Cannot flush before the merge is complete.
0264:                    _isFlushAllowed = false;
0265:
0266:                    entityT = recursiveMerge(entityT);
0267:
0268:                } catch (RuntimeException e) {
0269:                    exn = e;
0270:                } catch (Exception e) {
0271:                    exn = new EJBExceptionWrapper(e);
0272:                } finally {
0273:                    _isFlushAllowed = true;
0274:
0275:                    try {
0276:                        flushInternal();
0277:                    } catch (RuntimeException e) {
0278:                        if (exn == null)
0279:                            exn = e;
0280:                    } catch (Exception e) {
0281:                        if (exn == null)
0282:                            exn = new EJBExceptionWrapper(e);
0283:                    } finally {
0284:                        _mergingEntities.clear();
0285:                    }
0286:                }
0287:
0288:                // jpa/0o42, jpa/0o44
0289:                if (exn != null)
0290:                    throw exn;
0291:
0292:                return entityT;
0293:            }
0294:
0295:            /**
0296:             * Remove the instance.
0297:             */
0298:            public void remove(Object entity) {
0299:                try {
0300:                    if (entity == null)
0301:                        return;
0302:
0303:                    Entity instance = checkEntityType(entity, "remove");
0304:
0305:                    checkTransactionRequired("remove");
0306:
0307:                    if (log.isLoggable(Level.FINER))
0308:                        log.log(Level.FINER, L.l("removing entity class "
0309:                                + instance.getClass().getName() + " PK: "
0310:                                + instance.__caucho_getPrimaryKey()
0311:                                + " state: "
0312:                                + instance.__caucho_getEntityState()));
0313:
0314:                    EntityState state = instance.__caucho_getEntityState();
0315:
0316:                    if (EntityState.P_DELETING.ordinal() <= state.ordinal()) {
0317:                        if (log.isLoggable(Level.FINER))
0318:                            log.log(Level.FINER, L
0319:                                    .l("remove is ignoring entity in state "
0320:                                            + state));
0321:
0322:                        return;
0323:                    }
0324:
0325:                    // jpa/0k12
0326:                    if (instance.__caucho_getConnection() == null) {
0327:                        if (instance.__caucho_getEntityType() == null) {
0328:                            if (log.isLoggable(Level.FINER))
0329:                                log
0330:                                        .log(
0331:                                                Level.FINER,
0332:                                                L
0333:                                                        .l("remove is ignoring entity; performing only cascade post-remove"));
0334:
0335:                            // Ignore this entity; only post-remove child entities.
0336:                            instance.__caucho_cascadePostRemove(this );
0337:
0338:                            // jpa/0ga7
0339:                            return;
0340:                        } else
0341:                            throw new IllegalArgumentException(
0342:                                    L
0343:                                            .l(
0344:                                                    "remove() operation can only be applied to a managed entity. This entity instance '{0}' PK: '{1}' is detached which means it was probably removed or needs to be merged.",
0345:                                                    instance.getClass()
0346:                                                            .getName(),
0347:                                                    instance
0348:                                                            .__caucho_getPrimaryKey()));
0349:                    }
0350:
0351:                    // jpa/0h25, jpa/0i5e
0352:                    // Do not flush dependent objects for cascading persistence
0353:                    // when this entity is being removed.
0354:                    instance.__caucho_setEntityState(EntityState.P_DELETING);
0355:
0356:                    if (log.isLoggable(Level.FINER))
0357:                        log
0358:                                .log(
0359:                                        Level.FINER,
0360:                                        L
0361:                                                .l("remove is flushing any lazy cascading operation"));
0362:
0363:                    // jpa/1620
0364:                    // In particular, required for cascading persistence, since the cascade
0365:                    // is lazy until flush
0366:                    // jpa/0h25 flushInternal();
0367:                    // Cannot flush since the delete is lazy until flush, i.e.:
0368:                    // remove(A); // (*) __caucho_flush()
0369:                    // remove(B);
0370:                    // (*) would break a FK constraint if B has a reference to A.
0371:
0372:                    // jpa/0h26
0373:                    updateFlushPriority(instance);
0374:
0375:                    // jpa/0h25, jpa/0i5e
0376:                    // Restores original state.
0377:                    instance.__caucho_setEntityState(state);
0378:
0379:                    Object oldEntity;
0380:
0381:                    oldEntity = getEntity(instance.getClass().getName(),
0382:                            instance.__caucho_getPrimaryKey());
0383:
0384:                    // jpa/0ga4
0385:                    if (oldEntity == null)
0386:                        throw new IllegalArgumentException(
0387:                                L
0388:                                        .l("remove() operation can only be applied to a managed entity instance."));
0389:
0390:                    if (log.isLoggable(Level.FINER))
0391:                        log.log(Level.FINER, L
0392:                                .l("remove is performing cascade pre-remove"));
0393:
0394:                    // Pre-remove child entities.
0395:                    instance.__caucho_cascadePreRemove(this );
0396:
0397:                    if (log.isLoggable(Level.FINER))
0398:                        log
0399:                                .log(
0400:                                        Level.FINER,
0401:                                        L
0402:                                                .l("remove is performing delete on the target entity"));
0403:
0404:                    delete(instance);
0405:
0406:                    // jpa/0o30: flushes the owning side delete.
0407:                    // XXX: Cannot flush since the delete is lazy until flush.
0408:                    // jpa/0h25
0409:                    // instance.__caucho_flush();
0410:
0411:                    if (log.isLoggable(Level.FINER))
0412:                        log.log(Level.FINER, L
0413:                                .l("remove is performing cascade post-remove"));
0414:
0415:                    // jpa/0o30
0416:                    // Post-remove child entities.
0417:                    instance.__caucho_cascadePostRemove(this );
0418:
0419:                    if (log.isLoggable(Level.FINER))
0420:                        log.log(Level.FINER, L
0421:                                .l("DONE successful remove for entity class "
0422:                                        + instance.getClass().getName()
0423:                                        + " PK: "
0424:                                        + instance.__caucho_getPrimaryKey()));
0425:
0426:                } catch (RuntimeException e) {
0427:                    throw e;
0428:                } catch (Exception e) {
0429:                    throw new EJBExceptionWrapper(e);
0430:                }
0431:            }
0432:
0433:            /**
0434:             * Find by the primary key.
0435:             */
0436:            public <T> T find(Class<T> entityClass, Object primaryKey) {
0437:                // Do not flush while an entity is being loaded or merged.
0438:                boolean oldIsFlushAllowed = _isFlushAllowed;
0439:
0440:                try {
0441:                    // Do not flush while loading an entity.
0442:                    // Broken relationships would not pass the flush validation.
0443:                    _isFlushAllowed = false;
0444:
0445:                    T entity = (T) load(entityClass, primaryKey, true);
0446:
0447:                    if (!isActiveTransaction()) {
0448:                        // jpa/0o00
0449:                        detach();
0450:                    }
0451:
0452:                    return entity;
0453:                } catch (AmberObjectNotFoundException e) {
0454:                    if (_persistenceUnit.isJPA()) {
0455:                        // JPA: should not throw at all, returns null only.
0456:                        // log.log(Level.FINER, e.toString(), e);
0457:                        return null;
0458:                    }
0459:
0460:                    // ejb/0604
0461:                    throw e;
0462:                } catch (RuntimeException e) {
0463:                    throw e;
0464:                } catch (Exception e) {
0465:                    throw new EJBExceptionWrapper(e);
0466:                } finally {
0467:                    _isFlushAllowed = oldIsFlushAllowed;
0468:                }
0469:            }
0470:
0471:            /**
0472:             * Find by the primary key.
0473:             */
0474:            public <T> T getReference(Class<T> entityClass, Object primaryKey)
0475:                    throws EntityNotFoundException, IllegalArgumentException {
0476:                T reference = null;
0477:
0478:                try {
0479:                    // XXX: only needs to get a reference.
0480:
0481:                    reference = (T) load(entityClass, primaryKey, false);
0482:
0483:                    if (reference == null)
0484:                        throw new EntityNotFoundException(
0485:                                L
0486:                                        .l(
0487:                                                "entity with primary key {0} not found in getReference()",
0488:                                                primaryKey));
0489:
0490:                    /*
0491:                      if (! (entityClass.isAssignableFrom(Entity.class)))
0492:                        throw new IllegalArgumentException(L.l("getReference() operation can only be applied to an entity class"));
0493:                     */
0494:
0495:                    return reference;
0496:
0497:                } catch (EntityNotFoundException e) {
0498:                    throw e;
0499:                } catch (RuntimeException e) {
0500:                    throw new IllegalArgumentException(e);
0501:                } catch (Exception e) {
0502:                    throw new EJBExceptionWrapper(e);
0503:                }
0504:            }
0505:
0506:            /**
0507:             * Clears the connection
0508:             */
0509:            public void clear() {
0510:                _entitiesTop = 0;
0511:                _txEntitiesTop = 0;
0512:            }
0513:
0514:            /**
0515:             * Creates a query.
0516:             */
0517:            public Query createQuery(String sql) {
0518:                try {
0519:                    AbstractQuery queryProgram = parseQuery(sql, false);
0520:
0521:                    return new QueryImpl(queryProgram, this );
0522:                } catch (RuntimeException e) {
0523:                    throw new IllegalArgumentException(e);
0524:                } catch (Exception e) {
0525:                    throw new EJBExceptionWrapper(e);
0526:                }
0527:            }
0528:
0529:            /**
0530:             * Creates an instance of the named query
0531:             */
0532:            public Query createNamedQuery(String name) {
0533:                String sql = _persistenceUnit.getNamedQuery(name);
0534:
0535:                if (sql != null)
0536:                    return createQuery(sql);
0537:
0538:                NamedNativeQueryConfig nativeQuery = _persistenceUnit
0539:                        .getNamedNativeQuery(name);
0540:
0541:                sql = nativeQuery.getQuery();
0542:
0543:                String resultSetMapping = nativeQuery.getResultSetMapping();
0544:
0545:                if (!((resultSetMapping == null) || "".equals(resultSetMapping)))
0546:                    return createNativeQuery(sql, resultSetMapping);
0547:
0548:                String resultClass = nativeQuery.getResultClass();
0549:
0550:                AmberEntityHome entityHome = _persistenceUnit
0551:                        .getEntityHome(resultClass);
0552:
0553:                EntityType entityType = entityHome.getEntityType();
0554:
0555:                try {
0556:                    return createNativeQuery(sql, entityType.getInstanceClass());
0557:                } catch (Exception e) {
0558:                    throw new IllegalArgumentException(e);
0559:                }
0560:            }
0561:
0562:            /**
0563:             * Creates an instance of the named query
0564:             */
0565:            public Query createNativeQuery(String sql) {
0566:                sql = sql.trim();
0567:
0568:                char ch = sql.charAt(0);
0569:
0570:                if (ch == 'S' || ch == 's')
0571:                    throw new UnsupportedOperationException(
0572:                            L
0573:                                    .l("createNativeQuery(String sql) is not supported for select statements. Please use createNativeQuery(String sql, String map) or createNativeQuery(String sql, Class cl) to map the result to scalar values or bean classes."));
0574:
0575:                return createInternalNativeQuery(sql);
0576:            }
0577:
0578:            /**
0579:             * Creates an instance of the named query
0580:             */
0581:            public Query createNativeQuery(String sql, String map) {
0582:                // jpa/0y1-
0583:
0584:                SqlResultSetMappingConfig resultSet;
0585:
0586:                resultSet = _persistenceUnit.getSqlResultSetMapping(map);
0587:
0588:                if (resultSet == null)
0589:                    throw new IllegalArgumentException(
0590:                            L
0591:                                    .l(
0592:                                            "createNativeQuery() cannot create a native query for a result set named '{0}'",
0593:                                            map));
0594:
0595:                return createInternalNativeQuery(sql, resultSet);
0596:            }
0597:
0598:            /**
0599:             * Creates an instance of the native query
0600:             */
0601:            public Query createNativeQuery(String sql, Class type) {
0602:                SqlResultSetMappingConfig resultSet = new SqlResultSetMappingConfig();
0603:
0604:                EntityResultConfig entityResult = new EntityResultConfig();
0605:
0606:                entityResult.setEntityClass(type.getName());
0607:
0608:                resultSet.addEntityResult(entityResult);
0609:
0610:                return createInternalNativeQuery(sql, resultSet);
0611:            }
0612:
0613:            /**
0614:             * Refresh the state of the instance from the database.
0615:             */
0616:            public void refresh(Object entity) {
0617:                try {
0618:                    if (entity == null)
0619:                        return;
0620:
0621:                    if (!(entity instanceof  Entity))
0622:                        throw new IllegalArgumentException(
0623:                                L
0624:                                        .l(
0625:                                                "refresh() operation can only be applied to an entity instance. This object is of class '{0}'",
0626:                                                entity.getClass().getName()));
0627:
0628:                    checkTransactionRequired("refresh");
0629:
0630:                    Entity instance = (Entity) entity;
0631:
0632:                    String className = instance.getClass().getName();
0633:                    Object pk = instance.__caucho_getPrimaryKey();
0634:
0635:                    Entity oldEntity = getEntity(className, pk);
0636:
0637:                    if (oldEntity != null) {
0638:                        EntityState state = instance.__caucho_getEntityState();
0639:
0640:                        if (state.ordinal() <= EntityState.TRANSIENT.ordinal()
0641:                                || EntityState.P_DELETING.ordinal() <= state
0642:                                        .ordinal()) {
0643:                            throw new IllegalArgumentException(
0644:                                    L
0645:                                            .l(
0646:                                                    "refresh() operation can only be applied to a managed entity instance. The entity state is '{0}' for object of class '{0}' with PK '{1}'",
0647:                                                    className,
0648:                                                    pk,
0649:                                                    state == EntityState.TRANSIENT ? "TRANSIENT"
0650:                                                            : "DELETING or DELETED"));
0651:                        }
0652:                    } else
0653:                        throw new IllegalArgumentException(
0654:                                L
0655:                                        .l(
0656:                                                "refresh() operation can only be applied to a managed entity instance. There was no managed instance of class '{0}' with PK '{1}'",
0657:                                                className, pk));
0658:
0659:                    // Reset and refresh state.
0660:                    instance.__caucho_expire();
0661:                    instance.__caucho_makePersistent(this , (EntityType) null);
0662:                    instance.__caucho_retrieve_eager(this );
0663:                } catch (SQLException e) {
0664:                    throw new AmberRuntimeException(e);
0665:                }
0666:            }
0667:
0668:            /**
0669:             * Returns the flush mode.
0670:             */
0671:            public FlushModeType getFlushMode() {
0672:                return FlushModeType.AUTO;
0673:            }
0674:
0675:            /**
0676:             * Sets the extended type.
0677:             */
0678:            public void setExtended(boolean isExtended) {
0679:                _isExtended = isExtended;
0680:            }
0681:
0682:            /**
0683:             * Returns the flush mode.
0684:             */
0685:            public void setFlushMode(FlushModeType mode) {
0686:                throw new UnsupportedOperationException();
0687:            }
0688:
0689:            /**
0690:             * Locks the object.
0691:             */
0692:            public void lock(Object entity, LockModeType lockMode) {
0693:                throw new UnsupportedOperationException();
0694:            }
0695:
0696:            /**
0697:             * Returns the transaction.
0698:             */
0699:            public EntityTransaction getTransaction() {
0700:                if (_isXA)
0701:                    throw new IllegalStateException(
0702:                            L
0703:                                    .l("Cannot call EntityManager.getTransaction() inside a distributed transaction."));
0704:
0705:                if (_trans == null)
0706:                    _trans = new EntityTransactionImpl();
0707:
0708:                return _trans;
0709:            }
0710:
0711:            /**
0712:             * Returns true if open.
0713:             */
0714:            public boolean isOpen() {
0715:                return _persistenceUnit != null;
0716:            }
0717:
0718:            /**
0719:             * Registers with the local transaction.
0720:             */
0721:            void register() {
0722:                if (!_isRegistered) {
0723:                    if (!_isAppManaged)
0724:                        UserTransactionProxy.getInstance().enlistCloseResource(
0725:                                this );
0726:
0727:                    UserTransactionProxy.getInstance()
0728:                            .enlistBeginResource(this );
0729:                }
0730:
0731:                _isRegistered = true;
0732:            }
0733:
0734:            /**
0735:             * Joins the transaction.
0736:             */
0737:            public void joinTransaction() {
0738:                // XXX: jpa/0s46, jpa/0s47
0739:
0740:                _isInTransaction = true;
0741:            }
0742:
0743:            /**
0744:             * Gets the delegate.
0745:             */
0746:            public Object getDelegate() {
0747:                throw new UnsupportedOperationException();
0748:            }
0749:
0750:            /**
0751:             * Closes the context.
0752:             */
0753:            public void close() {
0754:                if (_persistenceUnit == null) {
0755:                    // jpa/0s45
0756:                    throw new IllegalStateException(
0757:                            "Entity manager is already closed.");
0758:                }
0759:
0760:                try {
0761:                    if (_isThreadConnection)
0762:                        _persistenceUnit.removeThreadConnection();
0763:
0764:                    _isRegistered = false;
0765:
0766:                    cleanup();
0767:                } catch (Exception e) {
0768:                    log.log(Level.FINER, e.toString(), e);
0769:                } finally {
0770:                    _persistenceUnit = null;
0771:                }
0772:            }
0773:
0774:            /**
0775:             * Returns the amber manager.
0776:             */
0777:            public AmberPersistenceUnit getAmberManager() {
0778:                return _persistenceUnit;
0779:            }
0780:
0781:            /**
0782:             * Registers a collection.
0783:             */
0784:            public void register(AmberCollection query) {
0785:                _queries.add(query);
0786:            }
0787:
0788:            /**
0789:             * Adds a completion
0790:             */
0791:            public void addCompletion(AmberCompletion completion) {
0792:                if (!_completionList.contains(completion))
0793:                    _completionList.add(completion);
0794:            }
0795:
0796:            /**
0797:             * Returns true if a transaction is active or
0798:             * this persistence context is extended.
0799:             */
0800:            public boolean isActiveTransaction() {
0801:                return _isInTransaction || _isExtended;
0802:            }
0803:
0804:            /**
0805:             * Returns true if a transaction is active.
0806:             */
0807:            public boolean isInTransaction() {
0808:                return _isInTransaction;
0809:            }
0810:
0811:            /**
0812:             * Returns the cache chunk size.
0813:             */
0814:            public int getCacheChunkSize() {
0815:                return 25;
0816:            }
0817:
0818:            public Object load(Class cl, Object key, boolean isEager)
0819:                    throws AmberException {
0820:                if (_persistenceUnit == null)
0821:                    throw new IllegalStateException(L
0822:                            .l("AmberConnection is closed"));
0823:
0824:                if (log.isLoggable(Level.FINER))
0825:                    log.log(Level.FINER, L.l("loading entity class "
0826:                            + cl.getName() + " PK: " + key));
0827:
0828:                Entity entity = null;
0829:
0830:                if (key == null)
0831:                    return null;
0832:
0833:                // ejb/0d01, jpa/0gh0, jpa/0g0k, jpa/0j5f
0834:                // if (shouldRetrieveFromCache())
0835:                entity = getEntity(cl.getName(), key);
0836:
0837:                if (entity != null) {
0838:                    // jpa/0s2d: if it contains such entity and we have
0839:                    // PersistenceContextType.TRANSACTION, the entity is
0840:                    // managed and we can just return it (otherwise it would
0841:                    // be detached and not be found in _entities).
0842:                    // XXX: for PersistenceContextType.EXTENDED???
0843:
0844:                    return entity;
0845:                }
0846:
0847:                _entityKey.init(cl, key);
0848:
0849:                boolean isXALoaded = false;
0850:
0851:                EntityItem cacheItem = loadCacheItem(cl, key, null);
0852:
0853:                if (cacheItem == null)
0854:                    return null;
0855:
0856:                AmberEntityHome entityHome = cacheItem.getEntityHome();
0857:
0858:                /*
0859:                boolean isLoad = true;
0860:
0861:                // jpa/0h13 as a negative test.
0862:                if (isActiveTransaction())
0863:                  isLoad = isEager;
0864:                 */
0865:                // jpa/0o03
0866:                boolean isLoad = isEager;
0867:
0868:                try {
0869:                    entity = cacheItem.createEntity(this , key);
0870:
0871:                    if (entity == null)
0872:                        return null;
0873:
0874:                    // The entity is added for eager loading
0875:                    addInternalEntity(entity);
0876:
0877:                    boolean isXA = isActiveTransaction();
0878:
0879:                    // jpa/0l48: inheritance loading optimization.
0880:                    // jpa/0h20: no transaction, copy from the existing cache item.
0881:                    // jpa/0l42: loading optimization.
0882:
0883:                    if (isLoad) {
0884:                        entity.__caucho_retrieve_eager(this );
0885:                    } else if (isXA) {
0886:                        // jpa/0v33: within a transaction, cannot copy from cache.
0887:                        entity.__caucho_retrieve_self(this );
0888:                    }
0889:                } catch (SQLException e) {
0890:                    if (_persistenceUnit.isJPA()) {
0891:                        log.log(Level.FINER, e.toString(), e);
0892:
0893:                        return null;
0894:                    }
0895:
0896:                    throw new AmberObjectNotFoundException(L.l(
0897:                            "{0}[{1}] is an unknown amber object",
0898:                            cl.getName(), key), e);
0899:                } catch (AmberObjectNotFoundException e) {
0900:                    // 0g0q: if the entity is not found, removes it from context.
0901:                    if (entity != null)
0902:                        removeEntity(entity);
0903:
0904:                    if (_persistenceUnit.isJPA())
0905:                        return null;
0906:
0907:                    throw e;
0908:                }
0909:
0910:                Entity txEntity = getTransactionEntity(entity.getClass()
0911:                        .getName(), entity.__caucho_getPrimaryKey());
0912:
0913:                // XXX: jpa/0v33
0914:                if (txEntity != null)
0915:                    setTransactionalState(txEntity);
0916:
0917:                return entity;
0918:            }
0919:
0920:            public EntityItem loadCacheItem(Class cl, Object key,
0921:                    AmberEntityHome entityHome) throws AmberException {
0922:                _entityKey.init(cl, key);
0923:
0924:                EntityItem cacheItem = _persistenceUnit.getEntity(_entityKey);
0925:
0926:                if (cacheItem != null)
0927:                    return cacheItem;
0928:
0929:                if (entityHome == null)
0930:                    entityHome = _persistenceUnit.getEntityHome(cl.getName());
0931:
0932:                if (entityHome == null) {
0933:                    throw new IllegalArgumentException(
0934:                            L
0935:                                    .l(
0936:                                            "'{0}' is an unknown class in persistence-unit '{1}'.  find() operation can only be applied if the entity class is specified in the scope of a persistence unit.",
0937:                                            cl.getName(), _persistenceUnit
0938:                                                    .getName()));
0939:                }
0940:
0941:                cacheItem = entityHome.findEntityItem(this , key);
0942:
0943:                if (cacheItem == null) {
0944:                    if (_persistenceUnit.isJPA())
0945:                        return null;
0946:
0947:                    // ejb/0604
0948:                    throw new AmberObjectNotFoundException(
0949:                            "amber find: no matching object " + cl.getName()
0950:                                    + "[" + key + "]");
0951:                }
0952:
0953:                if (!isActiveTransaction())
0954:                    cacheItem = _persistenceUnit.putEntity(cl, key, cacheItem);
0955:
0956:                return cacheItem;
0957:            }
0958:
0959:            /**
0960:             * Loads the object based on the class and primary key.
0961:             */
0962:            public Object load(String entityName, Object key)
0963:                    throws AmberException {
0964:                AmberEntityHome entityHome = _persistenceUnit
0965:                        .getEntityHome(entityName);
0966:
0967:                if (entityHome == null)
0968:                    return null;
0969:
0970:                Entity entity = null;
0971:
0972:                // XXX: ejb/0d01
0973:                // jpa/0y14 if (shouldRetrieveFromCache())
0974:                entity = getEntity(entityName, key);
0975:
0976:                if (entity != null)
0977:                    return entity;
0978:
0979:                try {
0980:                    entityHome.init();
0981:                } catch (ConfigException e) {
0982:                    throw new AmberException(e);
0983:                }
0984:
0985:                entity = (Entity) find(entityHome.getEntityType()
0986:                        .getInstanceClass(), key);
0987:
0988:                // addEntity(entity);
0989:
0990:                return entity;
0991:            }
0992:
0993:            /**
0994:             * Returns the entity for the connection.
0995:             */
0996:            public Entity getEntity(EntityItem item) {
0997:                Entity itemEntity = item.getEntity();
0998:
0999:                Class cl = itemEntity.getClass();
1000:                Object pk = itemEntity.__caucho_getPrimaryKey();
1001:
1002:                Entity entity = getEntity(cl.getName(), pk);
1003:
1004:                if (entity != null) {
1005:                    if (entity.__caucho_getEntityState().isManaged())
1006:                        return entity;
1007:                    // else
1008:                    // jpa/0g40: the copy object was created at some point in
1009:                    // findEntityItem, but it is still not loaded.
1010:                } else {
1011:                    try {
1012:                        entity = item.createEntity(this , pk);
1013:                    } catch (SQLException e) {
1014:                        throw new AmberRuntimeException(e);
1015:                    }
1016:
1017:                    /*
1018:                    // Create a new entity for the given class and primary key.
1019:                    try {
1020:                      entity = (Entity) cl.newInstance();
1021:                    } catch (Exception e) {
1022:                      throw new AmberRuntimeException(e);
1023:                    }
1024:                     */
1025:
1026:                    // entity.__caucho_setEntityState(EntityState.P_NON_TRANSACTIONAL);
1027:                    // entity.__caucho_setPrimaryKey(pk);
1028:                    // jpa/1000: avoids extra allocations.
1029:                    addInternalEntity(entity);
1030:                }
1031:
1032:                // jpa/0l43
1033:                //_persistenceUnit.copyFromCacheItem(this, entity, item);
1034:                // jpa/0l4a
1035:                entity.__caucho_retrieve_eager(this );
1036:
1037:                return entity;
1038:            }
1039:
1040:            /**
1041:             * Returns the entity for the connection.
1042:             */
1043:            public Entity getEntityLazy(EntityItem item) {
1044:                Entity itemEntity = item.getEntity();
1045:
1046:                Class cl = itemEntity.getClass();
1047:                Object pk = itemEntity.__caucho_getPrimaryKey();
1048:
1049:                Entity entity = getEntity(cl.getName(), pk);
1050:
1051:                if (entity != null) {
1052:                    if (entity.__caucho_getEntityState().isManaged())
1053:                        return entity;
1054:                    // else
1055:                    // jpa/0g40: the copy object was created at some point in
1056:                    // findEntityItem, but it is still not loaded.
1057:                } else {
1058:                    try {
1059:                        entity = item.createEntity(this , pk);
1060:                    } catch (SQLException e) {
1061:                        throw new AmberRuntimeException(e);
1062:                    }
1063:
1064:                    /*
1065:                    // Create a new entity for the given class and primary key.
1066:                    try {
1067:                      entity = (Entity) cl.newInstance();
1068:                    } catch (Exception e) {
1069:                      throw new AmberRuntimeException(e);
1070:                    }
1071:                     */
1072:
1073:                    // entity.__caucho_setEntityState(EntityState.P_NON_TRANSACTIONAL);
1074:                    // entity.__caucho_setPrimaryKey(pk);
1075:                    // jpa/1000: avoids extra allocations.
1076:                    addInternalEntity(entity);
1077:                }
1078:
1079:                return entity;
1080:            }
1081:
1082:            /**
1083:             * Loads the object based on itself.
1084:             */
1085:            public Object makePersistent(Object obj) throws SQLException {
1086:                Entity entity = (Entity) obj;
1087:
1088:                // check to see if exists
1089:
1090:                if (entity == null)
1091:                    throw new NullPointerException();
1092:
1093:                Class cl = entity.getClass();
1094:
1095:                // Entity oldEntity = getEntity(cl, entity.__caucho_getPrimaryKey());
1096:
1097:                AmberEntityHome entityHome;
1098:                entityHome = _persistenceUnit.getEntityHome(entity.getClass()
1099:                        .getName());
1100:
1101:                if (entityHome == null)
1102:                    throw new AmberException(L.l("entity has no matching home"));
1103:
1104:                entityHome.makePersistent(entity, this , false);
1105:
1106:                return entity;
1107:            }
1108:
1109:            /**
1110:             * Loads the object with the given class.
1111:             */
1112:            public Entity loadLazy(Class cl, String name, Object key) {
1113:                return loadLazy(cl.getName(), name, key);
1114:            }
1115:
1116:            /**
1117:             * Loads the object with the given class.
1118:             */
1119:            public Entity loadLazy(String className, String name, Object key) {
1120:                if (key == null)
1121:                    return null;
1122:
1123:                try {
1124:                    AmberEntityHome home = _persistenceUnit.getEntityHome(name);
1125:
1126:                    if (home == null)
1127:                        throw new RuntimeException(L.l(
1128:                                "no matching home for {0}", className));
1129:
1130:                    home.init();
1131:
1132:                    Object obj = load(home.getEntityType().getInstanceClass(),
1133:                            key, false);
1134:
1135:                    Entity entity = (Entity) obj;
1136:
1137:                    return entity;
1138:                } catch (SQLException e) {
1139:                    log.log(Level.WARNING, e.toString(), e);
1140:
1141:                    return null;
1142:                } catch (ConfigException e) {
1143:                    throw new AmberRuntimeException(e);
1144:                }
1145:            }
1146:
1147:            /**
1148:             * Loads the object with the given class.
1149:             */
1150:            public EntityItem findEntityItem(String name, Object key) {
1151:                try {
1152:                    AmberEntityHome home = _persistenceUnit.getEntityHome(name);
1153:
1154:                    if (home == null)
1155:                        throw new RuntimeException(L.l(
1156:                                "no matching home for {0}", name));
1157:
1158:                    home.init();
1159:
1160:                    return loadCacheItem(home.getJavaClass(), key, home);
1161:                } catch (RuntimeException e) {
1162:                    throw e;
1163:                } catch (Exception e) {
1164:                    throw new AmberRuntimeException(e);
1165:                }
1166:            }
1167:
1168:            /**
1169:             * Loads the object with the given class.
1170:             */
1171:            public EntityItem setEntityItem(String name, Object key,
1172:                    EntityItem item) {
1173:                try {
1174:                    AmberEntityHome home = _persistenceUnit.getEntityHome(name);
1175:
1176:                    if (home == null)
1177:                        throw new RuntimeException(L.l(
1178:                                "no matching home for {0}", name));
1179:
1180:                    home.init();
1181:
1182:                    return home.setEntityItem(key, item);
1183:                } catch (RuntimeException e) {
1184:                    throw e;
1185:                } catch (Exception e) {
1186:                    throw new AmberRuntimeException(e);
1187:                }
1188:            }
1189:
1190:            /**
1191:             * Loads the object with the given class.
1192:             *
1193:             * @param name the class name.
1194:             * @param key the key.
1195:             * @param notExpiringLoadMask the load mask bit that will not be reset
1196:             *        when the entity is expiring and reloaded to a new transaction.
1197:             *        Normally, the bit is only set in bidirectional one-to-one
1198:             *        relationships where we already know the other side has already
1199:             *        been loaded in the second or new transactions.
1200:             * @param notExpiringGroup the corresponding load group.
1201:             */
1202:            public Entity loadFromHome(String name, Object key) {
1203:                try {
1204:                    AmberEntityHome home = _persistenceUnit.getEntityHome(name);
1205:
1206:                    if (home == null)
1207:                        throw new RuntimeException(L.l(
1208:                                "no matching home for {0}", name));
1209:
1210:                    home.init();
1211:
1212:                    // jpa/0ge4, jpa/0o04, jpa/0o0b, jpa/0o0c: bidirectional optimization.
1213:                    return (Entity) load(home.getEntityType()
1214:                            .getInstanceClass(), key, true);
1215:                } catch (AmberObjectNotFoundException e) {
1216:                    if (_persistenceUnit.isJPA()) {
1217:                        if (log.isLoggable(Level.FINER))
1218:                            log.log(Level.FINER, e.toString(), e);
1219:
1220:                        // jpa/0h29
1221:                        return null;
1222:                    }
1223:
1224:                    throw e;
1225:                } catch (RuntimeException e) {
1226:                    throw e;
1227:                } catch (Exception e) {
1228:                    throw new AmberRuntimeException(e);
1229:                }
1230:            }
1231:
1232:            /**
1233:             * Loads the object with the given class.
1234:             */
1235:            public Object loadProxy(String name, Object key) {
1236:                if (key == null)
1237:                    return null;
1238:
1239:                AmberEntityHome home = _persistenceUnit.getEntityHome(name);
1240:
1241:                if (home == null)
1242:                    throw new RuntimeException(L.l("no matching home for {0}",
1243:                            name));
1244:
1245:                return loadProxy(home.getEntityType(), key);
1246:            }
1247:
1248:            /**
1249:             * Loads the object with the given class.
1250:             */
1251:            public Object loadProxy(EntityType type, Object key) {
1252:                if (key == null)
1253:                    return null;
1254:
1255:                Entity entity = getEntity(type.getInstanceClass().getName(),
1256:                        key);
1257:
1258:                if (entity != null) {
1259:                    // jpa/0m30
1260:                    return entity;
1261:                }
1262:
1263:                try {
1264:                    AmberEntityHome home = type.getHome();
1265:
1266:                    EntityItem item = home.findEntityItem(this , key);
1267:
1268:                    if (item == null)
1269:                        return null;
1270:
1271:                    EntityFactory factory = home.getEntityFactory();
1272:
1273:                    Object newEntity = factory.getEntity(this , item);
1274:
1275:                    if (_persistenceUnit.isJPA()) {
1276:                        // jpa/0h29: eager loading.
1277:                        Entity instance = (Entity) newEntity;
1278:                        setTransactionalState(instance);
1279:                    }
1280:
1281:                    return newEntity;
1282:                } catch (SQLException e) {
1283:                    log.log(Level.WARNING, e.toString(), e);
1284:
1285:                    return null;
1286:                }
1287:            }
1288:
1289:            /**
1290:             * Loads the CMP 2.1 object for the given entityItem
1291:             */
1292:            public Object loadProxy(EntityItem entityItem) {
1293:                Entity itemEntity = entityItem.getEntity();
1294:
1295:                /*
1296:                Class cl = itemEntity.getClass();
1297:                Object pk = itemEntity.__caucho_getPrimaryKey();
1298:
1299:                Entity entity = getEntity(cl.getName(), pk);
1300:
1301:                if (entity != null) {
1302:                  // jpa/0m30
1303:                  return entity;
1304:                }
1305:                 */
1306:
1307:                AmberEntityHome home = entityItem.getEntityHome();
1308:
1309:                EntityFactory factory = home.getEntityFactory();
1310:
1311:                Object newEntity = factory.getEntity(this , entityItem);
1312:
1313:                return newEntity;
1314:            }
1315:
1316:            /**
1317:             * Loads the object based on the class and primary key.
1318:             */
1319:            public Object load(Class cl, long intKey) throws AmberException {
1320:                AmberEntityHome entityHome = _persistenceUnit.getEntityHome(cl
1321:                        .getName());
1322:
1323:                if (entityHome == null)
1324:                    return null;
1325:
1326:                Object key = entityHome.toObjectKey(intKey);
1327:
1328:                return load(cl, key, true);
1329:            }
1330:
1331:            /**
1332:             * Loads the object based on the class and primary key.
1333:             */
1334:            public Object loadLazy(Class cl, long intKey) throws AmberException {
1335:                AmberEntityHome entityHome = _persistenceUnit.getEntityHome(cl
1336:                        .getName());
1337:
1338:                if (entityHome == null)
1339:                    return null;
1340:
1341:                Object key = entityHome.toObjectKey(intKey);
1342:
1343:                return loadLazy(cl, cl.getName(), key);
1344:            }
1345:
1346:            /**
1347:             * Matches the entity.
1348:             */
1349:            public Entity getEntity(String className, Object key) {
1350:                Entity[] entities = _entities;
1351:
1352:                for (int i = _entitiesTop - 1; i >= 0; i--) {
1353:                    Entity entity = entities[i];
1354:
1355:                    if (entity.__caucho_match(className, key)) {
1356:                        return entity;
1357:                    }
1358:                }
1359:
1360:                return null;
1361:            }
1362:
1363:            public Entity getEntity(int index) {
1364:                return _entities[index];
1365:            }
1366:
1367:            public Entity getEntity(Class cl, Object key) {
1368:                return getEntity(cl.getName(), key);
1369:            }
1370:
1371:            /**
1372:             * Returns the context entity that corresponds to the
1373:             * entity passed in. The entity passed in is normally a
1374:             * cache entity but might be the context entity itself
1375:             * when we want to make sure the reference is to an
1376:             * entity in the persistence context.
1377:             */
1378:            public Entity getEntity(Entity entity) {
1379:                if (entity == null)
1380:                    return null;
1381:
1382:                return getEntity(entity.getClass().getName(), entity
1383:                        .__caucho_getPrimaryKey());
1384:            }
1385:
1386:            public Entity getSubEntity(Class cl, Object key) {
1387:                Entity[] entities = _entities;
1388:
1389:                // jpa/0l43
1390:                for (int i = _entitiesTop - 1; i >= 0; i--) {
1391:                    Entity entity = entities[i];
1392:
1393:                    if (entity.__caucho_getPrimaryKey().equals(key)) {
1394:                        if (cl.isAssignableFrom(entity.getClass()))
1395:                            return entity;
1396:                    }
1397:                }
1398:
1399:                return null;
1400:            }
1401:
1402:            /**
1403:             * Gets the cache item referenced by __caucho_item
1404:             * from an entity of class/subclass cl.
1405:             */
1406:            public EntityItem getSubEntityCacheItem(Class cl, Object key) {
1407:                Entity[] entities = _entities;
1408:
1409:                // jpa/0l4a
1410:                for (int i = _entitiesTop - 1; i >= 0; i--) {
1411:                    Entity entity = _entities[i];
1412:
1413:                    if (entity.__caucho_getPrimaryKey().equals(key)) {
1414:                        if (cl.isAssignableFrom(entity.getClass()))
1415:                            return entity.__caucho_getCacheItem();
1416:                    }
1417:                }
1418:
1419:                return null;
1420:            }
1421:
1422:            public Entity getTransactionEntity(String className, Object key) {
1423:                Entity[] entities = _txEntities;
1424:
1425:                for (int i = _txEntitiesTop - 1; i >= 0; i--) {
1426:                    Entity entity = entities[i];
1427:
1428:                    if (entity.__caucho_match(className, key)) {
1429:                        return entity;
1430:                    }
1431:                }
1432:
1433:                return null;
1434:            }
1435:
1436:            public Entity getTransactionEntity(int index) {
1437:                return _txEntities[index];
1438:            }
1439:
1440:            /**
1441:             * Adds an entity.
1442:             */
1443:            /*
1444:            private boolean addEntity(Entity entity)
1445:            {
1446:              boolean added = false;
1447:
1448:              Object pk = entity.__caucho_getPrimaryKey();
1449:              String className = entity.getClass().getName();
1450:
1451:              Entity oldEntity = getEntity(className, pk);
1452:
1453:              // jpa/0s2d: if (! _entities.contains(entity)) {
1454:              if (oldEntity == null) {
1455:                addInternalEntity(entity);
1456:                added = true;
1457:              }
1458:              else if (isActiveTransaction()) { // jpa/0g06
1459:                int index = getTransactionEntity(className, pk);
1460:
1461:                // jpa/0s2d: if (! _txEntities.contains(entity)) {
1462:                if (index < 0) {
1463:                  addTxEntity(entity);
1464:                  added = true;
1465:                }
1466:              }
1467:
1468:              // jpa/0s2d: merge()
1469:              setTransactionalState(entity);
1470:
1471:              return added;
1472:            }
1473:             */
1474:
1475:            /**
1476:             * Adds a new entity for the given class name and key.
1477:             * The new entity object is supposed to be used as a
1478:             * copy from cache. This avoids the cache entity to
1479:             * be added to the context.
1480:             *
1481:             * @return null - if the entity is already in the context.
1482:             *         otherwise, it returns the new entity added to
1483:             *         the context.
1484:             */
1485:            public Entity addNewEntity(Class cl, Object key)
1486:                    throws InstantiationException, IllegalAccessException {
1487:                // jpa/0l43
1488:                Entity entity = getSubEntity(cl, key);
1489:
1490:                // If the entity is already in the context, it returns null.
1491:                if (entity != null)
1492:                    return null;
1493:
1494:                if (_persistenceUnit.isJPA()) {
1495:                    // XXX: needs to create based on the discriminator with inheritance.
1496:                    // Create a new entity for the given class and primary key.
1497:                    entity = (Entity) cl.newInstance();
1498:
1499:                    // jpa/0s2d
1500:                    entity
1501:                            .__caucho_setEntityState(EntityState.P_NON_TRANSACTIONAL);
1502:                } else {
1503:                    // HelperBean__Amber -> HelperBean
1504:                    String className = cl.getSuperclass().getName();
1505:
1506:                    AmberEntityHome entityHome = _persistenceUnit
1507:                            .getEntityHome(className);
1508:
1509:                    if (entityHome == null) {
1510:                        if (log.isLoggable(Level.FINER))
1511:                            log
1512:                                    .log(
1513:                                            Level.FINER,
1514:                                            L
1515:                                                    .l(
1516:                                                            "Amber.addNewEntity: home not found for entity (class: '{0}' PK: '{1}')",
1517:                                                            className, key));
1518:                        return null;
1519:                    }
1520:
1521:                    EntityFactory factory = entityHome.getEntityFactory();
1522:
1523:                    // TestBean__EJB
1524:                    Object value = factory.getEntity(key);
1525:
1526:                    Method cauchoGetBeanMethod = entityHome
1527:                            .getCauchoGetBeanMethod();
1528:                    if (cauchoGetBeanMethod != null) {
1529:                        try {
1530:                            // Bean
1531:                            entity = (Entity) cauchoGetBeanMethod.invoke(value,
1532:                                    new Object[0]);
1533:                            // entity.__caucho_makePersistent(aConn, item);
1534:                        } catch (Exception e) {
1535:                            log.log(Level.FINER, e.toString(), e);
1536:                        }
1537:                    }
1538:
1539:                    if (entity == null) {
1540:                        throw new IllegalStateException(
1541:                                L
1542:                                        .l("AmberConnection.addNewEntity unable to instantiate new entity with cauchoGetBeanMethod"));
1543:                    }
1544:                }
1545:
1546:                entity.__caucho_setPrimaryKey(key);
1547:
1548:                addInternalEntity(entity);
1549:
1550:                return entity;
1551:            }
1552:
1553:            /**
1554:             * Adds a new entity for the given class name and key.
1555:             */
1556:            public Entity loadEntity(Class cl, Object key, boolean isEager) {
1557:                if (key == null)
1558:                    return null;
1559:
1560:                // jpa/0l43
1561:                Entity entity = getSubEntity(cl, key);
1562:
1563:                // If the entity is already in the context, return it
1564:                if (entity != null)
1565:                    return entity;
1566:
1567:                if (_persistenceUnit.isJPA()) {
1568:                    // XXX: needs to create based on the discriminator with inheritance.
1569:                    // Create a new entity for the given class and primary key.
1570:                    try {
1571:                        entity = (Entity) load(cl, key, isEager);
1572:                    } catch (AmberException e) {
1573:                        throw new AmberRuntimeException(e);
1574:                    }
1575:                } else {
1576:                    // HelperBean__Amber -> HelperBean
1577:                    String className = cl.getSuperclass().getName();
1578:
1579:                    AmberEntityHome entityHome = _persistenceUnit
1580:                            .getEntityHome(className);
1581:
1582:                    if (entityHome == null) {
1583:                        if (log.isLoggable(Level.FINER))
1584:                            log
1585:                                    .log(
1586:                                            Level.FINER,
1587:                                            L
1588:                                                    .l(
1589:                                                            "Amber.addNewEntity: home not found for entity (class: '{0}' PK: '{1}')",
1590:                                                            className, key));
1591:                        return null;
1592:                    }
1593:
1594:                    EntityFactory factory = entityHome.getEntityFactory();
1595:
1596:                    // TestBean__EJB
1597:                    Object value = factory.getEntity(key);
1598:
1599:                    Method cauchoGetBeanMethod = entityHome
1600:                            .getCauchoGetBeanMethod();
1601:                    if (cauchoGetBeanMethod != null) {
1602:                        try {
1603:                            // Bean
1604:                            entity = (Entity) cauchoGetBeanMethod.invoke(value,
1605:                                    new Object[0]);
1606:                            // entity.__caucho_makePersistent(aConn, item);
1607:                        } catch (Exception e) {
1608:                            log.log(Level.FINER, e.toString(), e);
1609:                        }
1610:                    }
1611:
1612:                    if (entity == null) {
1613:                        throw new IllegalStateException(
1614:                                L
1615:                                        .l("AmberConnection.addNewEntity unable to instantiate new entity with cauchoGetBeanMethod"));
1616:                    }
1617:
1618:                    entity.__caucho_setPrimaryKey(key);
1619:
1620:                    addInternalEntity(entity);
1621:                }
1622:
1623:                return entity;
1624:            }
1625:
1626:            /**
1627:             * Removes an entity.
1628:             */
1629:            public boolean removeEntity(Entity entity) {
1630:                removeEntityImpl(entity);
1631:
1632:                if (isActiveTransaction())
1633:                    removeTxEntity(entity);
1634:
1635:                return true;
1636:            }
1637:
1638:            /**
1639:             * Loads the object based on itself.
1640:             */
1641:            public boolean contains(Object obj) {
1642:                if (obj == null)
1643:                    return false;
1644:
1645:                if (!(obj instanceof  Entity))
1646:                    throw new IllegalArgumentException(
1647:                            L
1648:                                    .l("contains() operation can only be applied to an entity instance."));
1649:
1650:                Entity entity = (Entity) obj;
1651:
1652:                // jpa/11a8
1653:                if (entity.__caucho_getConnection() != this )
1654:                    return false;
1655:
1656:                EntityState state = entity.__caucho_getEntityState();
1657:                if (isInTransaction() && !state.isTransactional()) {
1658:                    // jpa/11a6, jpa/1800
1659:                    return false;
1660:                }
1661:
1662:                // jpa/0j5f
1663:                if (EntityState.P_DELETING.ordinal() <= state.ordinal())
1664:                    return false;
1665:
1666:                return true;
1667:            }
1668:
1669:            /**
1670:             * Callback when the user transaction begins
1671:             */
1672:            public void begin(Transaction xa) {
1673:                try {
1674:                    xa.registerSynchronization(this );
1675:
1676:                    _isInTransaction = true;
1677:                    _isXA = true;
1678:                } catch (Exception e) {
1679:                    log.log(Level.WARNING, e.toString(), e);
1680:                }
1681:            }
1682:
1683:            /**
1684:             * Starts a transaction.
1685:             */
1686:            public void beginTransaction() throws SQLException {
1687:                _isInTransaction = true;
1688:
1689:                if (_conn != null && _isAutoCommit) {
1690:                    _isAutoCommit = false;
1691:                    _conn.setAutoCommit(false);
1692:                }
1693:
1694:                // _xid = _factory.getXid();
1695:            }
1696:
1697:            /**
1698:             * Sets XA.
1699:             */
1700:            public void setXA(boolean isXA) {
1701:                _isXA = isXA;
1702:                _isInTransaction = isXA;
1703:
1704:                if (isXA && !_isRegistered)
1705:                    register();
1706:            }
1707:
1708:            /**
1709:             * Commits a transaction.
1710:             */
1711:            public void commit() throws SQLException {
1712:                if (log.isLoggable(Level.FINER))
1713:                    log.log(Level.FINER, "AmberConnection.commit");
1714:
1715:                try {
1716:                    flushInternal();
1717:
1718:                    _xid = 0;
1719:                    if (_conn != null) {
1720:                        _conn.commit();
1721:                    }
1722:                } catch (RuntimeException e) {
1723:                    throw e;
1724:                } catch (SQLException e) {
1725:                    throw new IllegalStateException(e);
1726:                } catch (Exception e) {
1727:                    throw new EJBExceptionWrapper(e);
1728:                } finally {
1729:                    if (!_isXA)
1730:                        _isInTransaction = false;
1731:
1732:                    for (int i = 0; i < _txEntitiesTop; i++) {
1733:                        Entity entity = _txEntities[i];
1734:
1735:                        entity.__caucho_afterCommit();
1736:                    }
1737:
1738:                    if (log.isLoggable(Level.FINER))
1739:                        log.log(Level.FINER, "cleaning up txEntities");
1740:
1741:                    _txEntitiesTop = 0;
1742:                }
1743:            }
1744:
1745:            /**
1746:             * Callback before a utrans commit.
1747:             */
1748:            public void beforeCompletion() {
1749:                if (log.isLoggable(Level.FINER))
1750:                    log.log(Level.FINER, "AmberConnection.beforeCompletion");
1751:
1752:                try {
1753:                    beforeCommit();
1754:                    // XXX: need to figure out how to throw JPA exceptions at commit() time.
1755:                    // } catch (SQLException e) {
1756:                    //  throw e;
1757:                } catch (RuntimeException e) {
1758:                    // jpa/0ga5
1759:                    throw e;
1760:                } catch (Exception e) {
1761:                    log.log(Level.WARNING, e.toString(), e);
1762:                }
1763:            }
1764:
1765:            /**
1766:             * Callback after a utrans commit.
1767:             */
1768:            public void afterCompletion(int status) {
1769:                if (log.isLoggable(Level.FINER))
1770:                    log.log(Level.FINER, "AmberConnection.afterCompletion");
1771:
1772:                afterCommit(status == Status.STATUS_COMMITTED);
1773:                _isXA = false;
1774:                _isInTransaction = false;
1775:                _isRegistered = false; // ejb/0d19
1776:            }
1777:
1778:            /**
1779:             * Called before the commit phase
1780:             */
1781:            public void beforeCommit() throws SQLException {
1782:                if (log.isLoggable(Level.FINER))
1783:                    log.log(Level.FINER, "AmberConnection.beforeCommit");
1784:
1785:                try {
1786:                    flushInternal();
1787:                } catch (SQLException e) {
1788:                    throw e;
1789:                } catch (RuntimeException e) {
1790:                    throw e;
1791:                } catch (Exception e) {
1792:                    throw new RuntimeException(e);
1793:                }
1794:
1795:                /*
1796:                // jpa/0gh0
1797:                for (int i = _txEntities.size() - 1; i >= 0; i--) {
1798:                  Entity entity = _txEntities.get(i);
1799:
1800:                  // jpa/1500
1801:                  if (entity.__caucho_getEntityState() == EntityState.P_DELETED) {
1802:                    EntityType entityType = entity.__caucho_getEntityType();
1803:                    Object key = entity.__caucho_getPrimaryKey();
1804:                    EntityItem item = _persistenceUnit.getEntity(entityType, key);
1805:
1806:                    if (item == null) {
1807:                      // jpa/0ga8: entity has been removed and DELETE SQL was already flushed.
1808:                      continue;
1809:                    }
1810:                  }
1811:
1812:                  entity.__caucho_flush();
1813:                }
1814:                 */
1815:            }
1816:
1817:            /**
1818:             * Commits a transaction.
1819:             */
1820:            public void afterCommit(boolean isCommit) {
1821:                try {
1822:                    if (log.isLoggable(Level.FINER))
1823:                        log.log(Level.FINER, "AmberConnection.afterCommit: "
1824:                                + isCommit);
1825:
1826:                    if (!_isXA)
1827:                        _isInTransaction = false;
1828:
1829:                    if (isCommit) {
1830:                        if (_completionList.size() > 0) {
1831:                            _persistenceUnit.complete(_completionList);
1832:                        }
1833:                    }
1834:
1835:                    // jpa/0k20: clears the completion list in the
1836:                    // finally block so callbacks do not add a completion
1837:                    // which has been just removed.
1838:                    //
1839:                    // _completionList.clear();
1840:
1841:                    for (int i = 0; i < _txEntitiesTop; i++) {
1842:                        Entity entity = _txEntities[i];
1843:
1844:                        try {
1845:                            if (isCommit)
1846:                                entity.__caucho_afterCommit();
1847:                            else
1848:                                entity.__caucho_afterRollback();
1849:                        } catch (Exception e) {
1850:                            log.log(Level.WARNING, e.toString(), e);
1851:                        }
1852:                    }
1853:
1854:                    if (log.isLoggable(Level.FINER))
1855:                        log.log(Level.FINER, "cleaning up txEntities");
1856:
1857:                    _txEntitiesTop = 0;
1858:
1859:                    // jpa/0s2k
1860:                    Entity[] entities = _entities;
1861:                    for (int i = _entitiesTop - 1; i >= 0; i--) {
1862:                        // XXX: needs to check EXTENDED type.
1863:                        // jpa/0h07: persistence context TRANSACTION type.
1864:                        entities[i].__caucho_detach();
1865:                    }
1866:
1867:                    // jpa/0h60
1868:                    _entitiesTop = 0;
1869:
1870:                    // if (! isCommit) {
1871:                    // jpa/0j5c
1872:
1873:                    /* XXX: jpa/0k11 - avoids double rollback()
1874:                       Rollback is done from com.caucho.transaction.TransactionImpl
1875:                       to the pool item com.caucho.jca.PoolItem
1876:                       try {
1877:                         if (_conn != null)
1878:                           _conn.rollback();
1879:                       } catch (SQLException e) {
1880:                         throw new IllegalStateException(e);
1881:                       }
1882:                     */
1883:                    // }
1884:                } finally {
1885:                    _completionList.clear();
1886:                }
1887:            }
1888:
1889:            /**
1890:             * Rollbacks a transaction.
1891:             */
1892:            public void rollback() throws SQLException {
1893:                if (log.isLoggable(Level.FINER))
1894:                    log.log(Level.FINER, "AmberConnection.rollback");
1895:
1896:                try {
1897:                    flushInternal();
1898:
1899:                    _xid = 0;
1900:                    if (_conn != null) {
1901:                        _conn.rollback();
1902:                    }
1903:                } catch (RuntimeException e) {
1904:                    throw e;
1905:                } catch (SQLException e) {
1906:                    throw new IllegalStateException(e);
1907:                } catch (Exception e) {
1908:                    throw new EJBExceptionWrapper(e);
1909:                } finally {
1910:                    if (!_isXA)
1911:                        _isInTransaction = false;
1912:
1913:                    _completionList.clear();
1914:
1915:                    for (int i = 0; i < _txEntitiesTop; i++) {
1916:                        Entity entity = _txEntities[i];
1917:
1918:                        entity.__caucho_afterRollback();
1919:                    }
1920:
1921:                    _txEntitiesTop = 0;
1922:                }
1923:            }
1924:
1925:            /**
1926:             * Flushes managed entities.
1927:             */
1928:            public void flush() {
1929:                try {
1930:                    checkTransactionRequired("flush");
1931:
1932:                    flushInternal();
1933:                } catch (RuntimeException e) {
1934:                    throw e;
1935:                } catch (SQLException e) {
1936:                    throw new IllegalStateException(e);
1937:                } catch (Exception e) {
1938:                    throw new EJBExceptionWrapper(e);
1939:                }
1940:            }
1941:
1942:            /**
1943:             * Flushes managed entities.
1944:             */
1945:            public void flushNoChecks() {
1946:                try {
1947:                    flushInternal();
1948:                } catch (RuntimeException e) {
1949:                    throw e;
1950:                } catch (SQLException e) {
1951:                    throw new IllegalStateException(e);
1952:                } catch (Exception e) {
1953:                    throw new EJBExceptionWrapper(e);
1954:                }
1955:            }
1956:
1957:            /**
1958:             * Expires the entities
1959:             */
1960:            public void expire() throws SQLException {
1961:                Entity[] entities = _entities;
1962:                for (int i = _entitiesTop - 1; i >= 0; i--) {
1963:                    Entity entity = entities[i];
1964:
1965:                    // jpa/0j5e
1966:                    if (!entity.__caucho_getEntityState().isPersist())
1967:                        entity.__caucho_expire();
1968:                }
1969:            }
1970:
1971:            /**
1972:             * Returns the connection.
1973:             */
1974:            public Connection getConnection() throws SQLException {
1975:                DataSource readDataSource = _persistenceUnit
1976:                        .getReadDataSource();
1977:
1978:                if (!_isXA && !_isInTransaction && readDataSource != null) {
1979:                    if (_readConn == null) {
1980:                        _readConn = readDataSource.getConnection();
1981:                    } else if (_readConn.isClosed()) {
1982:                        closeConnectionImpl();
1983:                        _readConn = _persistenceUnit.getDataSource()
1984:                                .getConnection();
1985:                    }
1986:
1987:                    return _readConn;
1988:                }
1989:
1990:                if (_conn == null) {
1991:                    _conn = _persistenceUnit.getDataSource().getConnection();
1992:                    _isAutoCommit = true;
1993:                } else if (_conn.isClosed()) {
1994:                    closeConnectionImpl();
1995:                    _conn = _persistenceUnit.getDataSource().getConnection();
1996:                    _isAutoCommit = true;
1997:                }
1998:
1999:                if (_isXA) {
2000:                } else if (_isInTransaction && _isAutoCommit) {
2001:                    _isAutoCommit = false;
2002:                    _conn.setAutoCommit(false);
2003:                } else if (!_isInTransaction && !_isAutoCommit) {
2004:                    _isAutoCommit = true;
2005:                    _conn.setAutoCommit(true);
2006:                }
2007:
2008:                return _conn;
2009:            }
2010:
2011:            /**
2012:             * Prepares a statement.
2013:             */
2014:            public PreparedStatement prepareStatement(String sql)
2015:                    throws SQLException {
2016:                try {
2017:                    PreparedStatement pstmt = _preparedStatementMap.get(sql);
2018:
2019:                    if (pstmt == null) {
2020:                        Connection conn = getConnection();
2021:
2022:                        // XXX: avoids locking issues.
2023:                        if (_statements.size() > 0) {
2024:                            conn = _statements.get(0).getConnection();
2025:                        }
2026:
2027:                        // XXX: avoids locking issues.
2028:                        // See com.caucho.sql.UserConnection
2029:                        pstmt = conn.prepareStatement(sql,
2030:                                ResultSet.TYPE_FORWARD_ONLY,
2031:                                ResultSet.CONCUR_READ_ONLY);
2032:
2033:                        _statements.add(pstmt);
2034:
2035:                        _preparedStatementMap.put(sql, pstmt);
2036:                    }
2037:
2038:                    return pstmt;
2039:                } catch (SQLException e) {
2040:                    closeConnectionImpl();
2041:
2042:                    throw e;
2043:                }
2044:            }
2045:
2046:            /**
2047:             * Closes a statement.
2048:             */
2049:            public void closeStatement(String sql) throws SQLException {
2050:                PreparedStatement pstmt = _preparedStatementMap.remove(sql);
2051:
2052:                if (pstmt != null) {
2053:                    _statements.remove(pstmt);
2054:
2055:                    pstmt.close();
2056:                }
2057:            }
2058:
2059:            public static void close(ResultSet rs) {
2060:                try {
2061:                    if (rs != null)
2062:                        rs.close();
2063:                } catch (SQLException e) {
2064:                    throw new AmberRuntimeException(e);
2065:                }
2066:            }
2067:
2068:            /**
2069:             * Prepares an insert statement.
2070:             */
2071:            public PreparedStatement prepareInsertStatement(String sql)
2072:                    throws SQLException {
2073:                PreparedStatement pstmt = null;
2074:
2075:                try {
2076:                    pstmt = _preparedStatementMap.get(sql);
2077:
2078:                    if (pstmt == null) {
2079:                        Connection conn = getConnection();
2080:
2081:                        // XXX: avoids locking issues.
2082:                        if (_statements.size() > 0) {
2083:                            conn = _statements.get(0).getConnection();
2084:                        }
2085:
2086:                        if (_persistenceUnit.hasReturnGeneratedKeys())
2087:                            pstmt = conn.prepareStatement(sql,
2088:                                    Statement.RETURN_GENERATED_KEYS);
2089:                        else {
2090:                            // XXX: avoids locking issues.
2091:                            // See com.caucho.sql.UserConnection
2092:                            pstmt = conn.prepareStatement(sql,
2093:                                    ResultSet.TYPE_FORWARD_ONLY,
2094:                                    ResultSet.CONCUR_READ_ONLY);
2095:                        }
2096:
2097:                        _statements.add(pstmt);
2098:
2099:                        _preparedStatementMap.put(sql, pstmt);
2100:                    }
2101:                } catch (SQLException e) {
2102:                    closeStatement(sql);
2103:                }
2104:
2105:                return pstmt;
2106:            }
2107:
2108:            /**
2109:             * Makes the object transactional.
2110:             *
2111:             * @param obj the object to save
2112:             *
2113:             * @return the proxy for the saved object
2114:             */
2115:            public void makeTransactional(Entity entity) {
2116:                // ejb/0600
2117:                if (!_persistenceUnit.isJPA())
2118:                    return;
2119:
2120:                /* XXX: jpa/0l43
2121:                   EntityState state = entity.__caucho_getEntityState();
2122:
2123:                   if (EntityState.TRANSIENT.ordinal() < state.ordinal()
2124:                       && state.ordinal() < EntityState.P_DELETING.ordinal()) {
2125:                     // jpa/0g06
2126:                     addEntity(entity);
2127:                   }
2128:                 */
2129:
2130:                /*
2131:                  if (! isInTransaction())
2132:                    throw new AmberRuntimeException(L.l("makePersistent must be called from within a transaction."));
2133:
2134:                  if (! (obj instanceof Entity)) {
2135:                    throw new AmberRuntimeException(L.l("`{0}' is not a known entity class.",
2136:                                                    obj.getClass().getName()));
2137:                  }
2138:                 */
2139:            }
2140:
2141:            /**
2142:             * Updates the database with the values in object.  If the object does
2143:             * not exist, throws an exception.
2144:             *
2145:             * @param obj the object to update
2146:             */
2147:            public void update(Object obj) {
2148:                /*
2149:                  for (int i = _entities.size() - 1; i >= 0; i--) {
2150:                    Entity entity = _entities.get(i);
2151:
2152:                    if (entity.__caucho_match(obj)) {
2153:                      entity.__caucho_load(obj);
2154:
2155:                      return entity;
2156:                    }
2157:                  }
2158:                 */
2159:
2160:                /*
2161:                  Class cl = obj.getClass();
2162:
2163:                  EntityHome home = _factory.getHome(cl);
2164:
2165:                  if (home == null)
2166:                    throw new AmberException(L.l("no matching home for {0}", cl.getName()));
2167:
2168:                  Object key = home.getKeyFromEntity(obj);
2169:
2170:                  Entity entity = getEntity(cl, key);
2171:
2172:                  if (entity == null) {
2173:                    entity = home.load(this, key);
2174:
2175:                    addEntity(entity);
2176:                  }
2177:
2178:                  entity.__caucho_loadFromObject(obj);
2179:
2180:                  return entity;
2181:                 */
2182:            }
2183:
2184:            /**
2185:             * Saves the object.
2186:             *
2187:             * @param obj the object to create
2188:             */
2189:            public void create(Object obj) throws SQLException {
2190:                // ejb/0g22 exception handling
2191:                try {
2192:
2193:                    createInternal(obj);
2194:
2195:                } catch (RuntimeException e) {
2196:                    throw e;
2197:                } catch (Exception e) {
2198:                    throw new EJBExceptionWrapper(e);
2199:                }
2200:            }
2201:
2202:            /**
2203:             * Saves the object.
2204:             *
2205:             * @param obj the object to create
2206:             */
2207:            public void create(String homeName, Object obj) throws SQLException {
2208:                // ejb/0g22 exception handling
2209:                try {
2210:
2211:                    createInternal(homeName, obj);
2212:
2213:                } catch (RuntimeException e) {
2214:                    throw e;
2215:                } catch (Exception e) {
2216:                    throw new EJBExceptionWrapper(e);
2217:                }
2218:            }
2219:
2220:            /**
2221:             * Saves the object.
2222:             *
2223:             * @param obj the object to create
2224:             */
2225:            public void create(AmberEntityHome home, Object obj)
2226:                    throws SQLException {
2227:                // ejb/0g22 exception handling
2228:                try {
2229:
2230:                    createInternal(home, obj);
2231:
2232:                } catch (RuntimeException e) {
2233:                    throw e;
2234:                } catch (Exception e) {
2235:                    throw new EJBExceptionWrapper(e);
2236:                }
2237:            }
2238:
2239:            /**
2240:             * Updates the object.
2241:             */
2242:            public void update(Entity entity) {
2243:                if (entity == null)
2244:                    return;
2245:
2246:                // jpa/0g0i
2247:                if (entity.__caucho_getEntityType() == null)
2248:                    return;
2249:
2250:                // XXX: also needs to check PersistenceContextType.TRANSACTION/EXTENDED.
2251:                // jpa/0k10
2252:                if (!isActiveTransaction())
2253:                    return;
2254:
2255:                Table table = entity.__caucho_getEntityType().getTable();
2256:
2257:                Object key = entity.__caucho_getPrimaryKey();
2258:
2259:                addCompletion(new RowInvalidateCompletion(table.getName(), key));
2260:
2261:                // jpa/0ga8, jpa/0s2d if (! _txEntities.contains(entity)) {
2262:                Entity oldEntity = getTransactionEntity(entity.getClass()
2263:                        .getName(), key);
2264:
2265:                if (oldEntity == null) {
2266:                    addTxEntity(entity);
2267:                } else {
2268:                    // XXX:
2269:                    /*
2270:                    // jpa/0s2d
2271:                    Entity oldEntity = _txEntities.get(index);
2272:                    _txEntities.set(index, entity);
2273:                     */
2274:                }
2275:            }
2276:
2277:            /**
2278:             * Deletes the object.
2279:             *
2280:             * @param obj the object to delete
2281:             */
2282:            public void delete(Entity entity) throws SQLException {
2283:                Entity oldEntity = getEntity(entity.getClass().getName(),
2284:                        entity.__caucho_getPrimaryKey());
2285:
2286:                if (oldEntity == null) {
2287:                    throw new IllegalStateException(
2288:                            L
2289:                                    .l(
2290:                                            "AmberEntity[{0}:{1}] cannot be deleted since it is not managed",
2291:                                            entity.getClass().getName(), entity
2292:                                                    .__caucho_getPrimaryKey()));
2293:                    /*
2294:                      EntityType entityType = entity.__caucho_getEntityType();
2295:
2296:                      if (entityType == null)
2297:                        return;
2298:                      // throw new AmberException(L.l("entity has no entityType"));
2299:
2300:                      AmberEntityHome entityHome = entityType.getHome();
2301:                      //entityHome = _persistenceUnit.getEntityHome(entity.getClass().getName());
2302:
2303:                      if (entityHome == null)
2304:                        throw new AmberException(L.l("entity has no matching home"));
2305:
2306:                      // XXX: this makes no sense
2307:                      entityHome.makePersistent(entity, this, true);
2308:
2309:                      addEntity(entity);
2310:                     */
2311:                } else {
2312:                    // XXX: jpa/0k12
2313:                    oldEntity.__caucho_setConnection(this );
2314:
2315:                    entity = oldEntity;
2316:                }
2317:
2318:                entity.__caucho_delete();
2319:            }
2320:
2321:            /**
2322:             * Creates a query object from a query string.
2323:             *
2324:             * @param query a Hibernate query
2325:             */
2326:            public AmberQuery prepareQuery(String queryString)
2327:                    throws AmberException {
2328:                return prepareQuery(queryString, false);
2329:            }
2330:
2331:            /**
2332:             * Creates a query object from a query string.
2333:             *
2334:             * @param query a Hibernate query
2335:             */
2336:            public AmberQuery prepareLazyQuery(String queryString)
2337:                    throws AmberException {
2338:                return prepareQuery(queryString, true);
2339:            }
2340:
2341:            /**
2342:             * Creates a query object from a query string.
2343:             *
2344:             * @param query a Hibernate query
2345:             */
2346:            public AmberQuery prepareUpdate(String queryString)
2347:                    throws AmberException {
2348:                return prepareQuery(queryString, true);
2349:            }
2350:
2351:            /**
2352:             * Creates a query object from a query string.
2353:             *
2354:             * @param query a Hibernate query
2355:             */
2356:            private AmberQuery prepareQuery(String queryString, boolean isLazy)
2357:                    throws AmberException {
2358:                AbstractQuery queryProgram = parseQuery(queryString, isLazy);
2359:
2360:                UserQuery query = new UserQuery(queryProgram);
2361:
2362:                query.setSession(this );
2363:
2364:                return query;
2365:            }
2366:
2367:            /**
2368:             * Creates a query object from a query string.
2369:             *
2370:             * @param query a Hibernate query
2371:             */
2372:            public AbstractQuery parseQuery(String sql, boolean isLazy)
2373:                    throws AmberException {
2374:                try {
2375:                    _persistenceUnit.initEntityHomes();
2376:                } catch (Exception e) {
2377:                    throw AmberRuntimeException.create(e);
2378:                }
2379:
2380:                AbstractQuery query = _persistenceUnit.getQueryParseCache(sql);
2381:
2382:                if (query == null) {
2383:                    QueryParser parser = new QueryParser(sql);
2384:
2385:                    parser.setPersistenceUnit(_persistenceUnit);
2386:                    parser.setLazyResult(isLazy);
2387:
2388:                    query = parser.parse();
2389:
2390:                    _persistenceUnit.putQueryParseCache(sql, query);
2391:                }
2392:
2393:                return query;
2394:            }
2395:
2396:            /**
2397:             * Select a list of objects with a Hibernate query.
2398:             *
2399:             * @param query the hibernate query
2400:             *
2401:             * @return the query results.
2402:             */
2403:            public ResultSet query(String hsql) throws SQLException {
2404:                AmberQuery query = prepareQuery(hsql);
2405:
2406:                return query.executeQuery();
2407:            }
2408:
2409:            /**
2410:             * Returns the cache chunk.
2411:             *
2412:             * @param sql the SQL for the cache chunk
2413:             * @param args the filled parameters for the cache chunk
2414:             * @param startRow the starting row for the cache chunk
2415:             */
2416:            public ResultSetCacheChunk getQueryCacheChunk(String sql,
2417:                    Object[] args, int startRow) {
2418:                _queryKey.init(sql, args, startRow);
2419:
2420:                return _persistenceUnit.getQueryChunk(_queryKey);
2421:            }
2422:
2423:            /**
2424:             * Returns the result set meta data from cache.
2425:             */
2426:            public ResultSetMetaData getQueryMetaData() {
2427:                return _persistenceUnit.getQueryMetaData(_queryKey);
2428:            }
2429:
2430:            /**
2431:             * Sets the cache chunk.
2432:             *
2433:             * @param sql the SQL for the cache chunk
2434:             * @param args the filled parameters for the cache chunk
2435:             * @param startRow the starting row for the cache chunk
2436:             * @param cacheChunk the new value of the cache chunk
2437:             */
2438:            public void putQueryCacheChunk(String sql, Object[] args,
2439:                    int startRow, ResultSetCacheChunk cacheChunk,
2440:                    ResultSetMetaData cacheMetaData) {
2441:                QueryCacheKey key = new QueryCacheKey();
2442:                Object[] newArgs = new Object[args.length];
2443:
2444:                System.arraycopy(args, 0, newArgs, 0, args.length);
2445:
2446:                key.init(sql, newArgs, startRow);
2447:
2448:                _persistenceUnit.putQueryChunk(key, cacheChunk);
2449:                _persistenceUnit.putQueryMetaData(key, cacheMetaData);
2450:            }
2451:
2452:            /**
2453:             * Updates the database with a query
2454:             *
2455:             * @param query the hibernate query
2456:             *
2457:             * @return the query results.
2458:             */
2459:            public int update(String hsql) throws SQLException {
2460:                AmberQuery query = prepareUpdate(hsql);
2461:
2462:                return query.executeUpdate();
2463:            }
2464:
2465:            /**
2466:             * Select a list of objects with a Hibernate query.
2467:             *
2468:             * @param query the hibernate query
2469:             *
2470:             * @return the query results.
2471:             */
2472:            public List find(String hsql) throws SQLException {
2473:                AmberQuery query = prepareQuery(hsql);
2474:
2475:                return query.list();
2476:            }
2477:
2478:            /**
2479:             * Cleans up the connection.
2480:             */
2481:            public void cleanup() {
2482:                if (log.isLoggable(Level.FINER))
2483:                    log.log(Level.FINER, "AmberConnection.cleanup");
2484:
2485:                try {
2486:                    // XXX: also needs to check PersistenceContextType.TRANSACTION/EXTENDED.
2487:                    // jpa/0g04
2488:                    if (isActiveTransaction()) {
2489:                        flushInternal();
2490:                    }
2491:                } catch (RuntimeException e) {
2492:                    throw e;
2493:                } catch (SQLException e) {
2494:                    throw new IllegalStateException(e);
2495:                } catch (Exception e) {
2496:                    throw new EJBExceptionWrapper(e);
2497:                } finally {
2498:                    _depth = 0;
2499:
2500:                    for (int i = _entitiesTop - 1; i >= 0; i--) {
2501:                        _entities[i].__caucho_detach();
2502:                    }
2503:
2504:                    _entitiesTop = 0;
2505:                    _txEntitiesTop = 0;
2506:                    _completionList.clear();
2507:
2508:                    freeConnection();
2509:                }
2510:            }
2511:
2512:            /**
2513:             * Pushes the depth.
2514:             */
2515:            public void pushDepth() {
2516:                // these aren't necessary because the AmberConnection is added as
2517:                // a close callback to the UserTransaction
2518:            }
2519:
2520:            /**
2521:             * Pops the depth.
2522:             */
2523:            public void popDepth() {
2524:            }
2525:
2526:            /**
2527:             * Frees the connection.
2528:             */
2529:            public void freeConnection() {
2530:                closeConnectionImpl();
2531:            }
2532:
2533:            /**
2534:             * Frees the connection.
2535:             */
2536:            private void closeConnectionImpl() {
2537:                Connection conn = _conn;
2538:                _conn = null;
2539:
2540:                Connection readConn = _readConn;
2541:                _readConn = null;
2542:
2543:                boolean isAutoCommit = _isAutoCommit;
2544:                _isAutoCommit = true;
2545:
2546:                try {
2547:                    if (conn != null && !isAutoCommit)
2548:                        conn.setAutoCommit(true);
2549:                } catch (SQLException e) {
2550:                }
2551:
2552:                for (Statement stmt : _statements) {
2553:                    try {
2554:                        stmt.close();
2555:                    } catch (Exception e) {
2556:                        log.log(Level.WARNING, e.toString(), e);
2557:                    }
2558:                }
2559:
2560:                try {
2561:                    _preparedStatementMap.clear();
2562:                    _statements.clear();
2563:
2564:                    if (conn != null)
2565:                        conn.close();
2566:
2567:                    if (readConn != null)
2568:                        readConn.close();
2569:                } catch (Exception e) {
2570:                    log.log(Level.WARNING, e.toString(), e);
2571:                }
2572:            }
2573:
2574:            public String toString() {
2575:                if (_persistenceUnit != null)
2576:                    return "AmberConnection[" + _persistenceUnit.getName()
2577:                            + "]";
2578:                else
2579:                    return "AmberConnection[closed]";
2580:            }
2581:
2582:            /**
2583:             * Finalizer.
2584:             */
2585:            public void finalize() {
2586:                cleanup();
2587:            }
2588:
2589:            /**
2590:             * Returns true when cache items can be used.
2591:             */
2592:            public boolean shouldRetrieveFromCache() {
2593:                // ejb/0d01
2594:                return (!isActiveTransaction());
2595:            }
2596:
2597:            public void setTransactionalState(Entity entity) {
2598:                if (isActiveTransaction()) {
2599:                    // jpa/0ga8
2600:                    entity.__caucho_setConnection(this );
2601:
2602:                    // jpa/0j5f
2603:                    EntityState state = entity.__caucho_getEntityState();
2604:
2605:                    //if (state.ordinal() < EntityState.P_DELETING.ordinal())
2606:                    if (state == EntityState.P_NON_TRANSACTIONAL)
2607:                        entity
2608:                                .__caucho_setEntityState(EntityState.P_TRANSACTIONAL);
2609:                }
2610:            }
2611:
2612:            public boolean isCacheEntity(Entity entity) {
2613:                return entity == getCacheEntity(entity, true);
2614:            }
2615:
2616:            public Entity getCacheEntity(Entity entity) {
2617:                return getCacheEntity(entity, false);
2618:            }
2619:
2620:            public Entity getCacheEntity(Entity entity, boolean isDebug) {
2621:                // jpa/0h0a
2622:
2623:                if (entity == null)
2624:                    return null;
2625:
2626:                // XXX: jpa/0h20, the cache entity is only available after commit.
2627:                Entity cacheEntity = entity.__caucho_getCacheEntity();
2628:
2629:                if (cacheEntity != null)
2630:                    return cacheEntity;
2631:
2632:                return getCacheEntity(entity.getClass(), entity
2633:                        .__caucho_getPrimaryKey(), isDebug);
2634:            }
2635:
2636:            public Entity getCacheEntity(Class cl, Object pk) {
2637:                return getCacheEntity(cl, pk, false);
2638:            }
2639:
2640:            // jpa/0h20
2641:            public Entity getCacheEntity(Class cl, Object pk, boolean isDebug) {
2642:                if (pk == null)
2643:                    return null;
2644:
2645:                String className = cl.getName();
2646:
2647:                AmberEntityHome entityHome = _persistenceUnit
2648:                        .getEntityHome(className);
2649:
2650:                if (entityHome == null) {
2651:                    if (log.isLoggable(Level.FINER))
2652:                        log
2653:                                .log(
2654:                                        Level.FINER,
2655:                                        L
2656:                                                .l(
2657:                                                        "Home not found for entity (class: '{0}' PK: '{1}')",
2658:                                                        className, pk));
2659:                    return null;
2660:                }
2661:
2662:                EntityType rootType = entityHome.getRootType();
2663:
2664:                EntityItem item = _persistenceUnit.getEntity(rootType, pk);
2665:
2666:                if (item == null)
2667:                    return null;
2668:
2669:                // jpa/0o0b
2670:                if (isDebug)
2671:                    return item.getEntity();
2672:
2673:                // XXX: jpa/0h31, expires the child cache entity.
2674:                if (isActiveTransaction()) {
2675:                    Entity txEntity = getTransactionEntity(className, pk);
2676:
2677:                    EntityState state = null;
2678:
2679:                    if (txEntity != null)
2680:                        state = txEntity.__caucho_getEntityState();
2681:                    else
2682:                        // jpa/0o0b || ! state.isManaged()) {
2683:                        item.getEntity().__caucho_expire();
2684:
2685:                    return null;
2686:                }
2687:
2688:                return item.getEntity();
2689:            }
2690:
2691:            //
2692:            // private
2693:            //
2694:            // throws Exception (for jpa)
2695:            //
2696:            // ejb/0g22 (cmp) expects exception handling in
2697:            // the public methods. See public void create(Object) above.
2698:
2699:            /**
2700:             * Adds an entity to the context, assuming it has not been added yet.
2701:             * Also, if there is a transaction, adds the entity to the list of
2702:             * transactional entities.
2703:             */
2704:            private void addInternalEntity(Entity entity) {
2705:                if (log.isLoggable(Level.FINEST)) {
2706:                    log.log(Level.FINEST, L.l(
2707:                            "amber {0}[{1}] addInternalEntity", entity
2708:                                    .getClass().getName(), entity
2709:                                    .__caucho_getPrimaryKey()));
2710:                }
2711:
2712:                addEntity(entity);
2713:
2714:                // jpa/0g06
2715:                if (isActiveTransaction()) {
2716:                    addTxEntity(entity);
2717:
2718:                    // jpa/0s2d: merge()
2719:                    setTransactionalState(entity);
2720:                }
2721:            }
2722:
2723:            /**
2724:             * Saves the object.
2725:             *
2726:             * @param obj the object to create
2727:             */
2728:            private void createInternal(Object obj) throws Exception {
2729:                AmberEntityHome home = null;
2730:
2731:                Class cl = obj.getClass();
2732:
2733:                for (; home == null && cl != null; cl = cl.getSuperclass()) {
2734:                    home = _persistenceUnit.getHome(cl);
2735:                }
2736:
2737:                if (home == null)
2738:                    throw new AmberException(L.l(
2739:                            "`{0}' is not a known entity class.", obj
2740:                                    .getClass().getName()));
2741:
2742:                createInternal(home, obj);
2743:            }
2744:
2745:            /**
2746:             * Saves the object.
2747:             *
2748:             * @param obj the object to create
2749:             */
2750:            private void createInternal(String homeName, Object obj)
2751:                    throws Exception {
2752:                AmberEntityHome home = _persistenceUnit.getEntityHome(homeName);
2753:
2754:                if (home == null)
2755:                    throw new AmberException(L.l(
2756:                            "`{0}' is not a known entity class.", obj
2757:                                    .getClass().getName()));
2758:
2759:                createInternal(home, obj);
2760:            }
2761:
2762:            /**
2763:             * Saves the object.
2764:             *
2765:             * @param obj the object to create
2766:             */
2767:            private void createInternal(AmberEntityHome home, Object obj)
2768:                    throws Exception {
2769:                // XXX: flushing things like delete might be useful?
2770:                // XXX: the issue is a flush can break FK constraints and
2771:                //      fail prematurely (jpa/0h26).
2772:                // commented out: flushInternal();
2773:
2774:                if (contains(obj))
2775:                    return;
2776:
2777:                Entity entity = (Entity) obj;
2778:
2779:                // jpa/0g0k: cannot call home.save because of jpa exception handling.
2780:                if (_persistenceUnit.isJPA()) {
2781:                    // See persistInternal(): entity.__caucho_cascadePrePersist(this);
2782:
2783:                    addEntity(entity);
2784:
2785:                    // jpa/0ga2
2786:                    entity.__caucho_lazy_create(this , home.getEntityType());
2787:
2788:                    // See persistInternal(): entity.__caucho_cascadePostPersist(this);
2789:                } else
2790:                    home.save(this , entity);
2791:
2792:                // jpa/0h25
2793:                // XXX: not correct, since we need to keep the P_PERSIST state around
2794:                // and P_PERSIST is a transactional state
2795:                // setTransactionalState(entity);
2796:
2797:                // jpa/0g0i
2798:                Table table = home.getEntityType().getTable();
2799:                addCompletion(new RowInsertCompletion(table.getName()));
2800:            }
2801:
2802:            private void checkTransactionRequired(String operation)
2803:                    throws TransactionRequiredException, SQLException {
2804:                // XXX: also needs to check PersistenceContextType.TRANSACTION/EXTENDED.
2805:
2806:                if (!(_isXA || isActiveTransaction()))
2807:                    throw new TransactionRequiredException(
2808:                            L
2809:                                    .l(
2810:                                            "{0}() operation can only be executed in the scope of a transaction or with an extended persistence context.",
2811:                                            operation));
2812:            }
2813:
2814:            private Entity checkEntityType(Object entity, String operation) {
2815:                if (!(entity instanceof  Entity))
2816:                    throw new IllegalArgumentException(
2817:                            L
2818:                                    .l(
2819:                                            "{0}() operation can only be applied to an entity instance. If the argument is an entity, the corresponding class must be specified in the scope of a persistence unit.",
2820:                                            operation));
2821:
2822:                if (_persistenceUnit.isJPA()) {
2823:                    String className = entity.getClass().getName();
2824:
2825:                    EntityType entityType = (EntityType) _persistenceUnit
2826:                            .getEntityType(className);
2827:
2828:                    // jpa/0m08
2829:                    if (entityType == null) {
2830:                        throw new IllegalArgumentException(
2831:                                L
2832:                                        .l(
2833:                                                "{0}() operation can only be applied to an entity instance. If the argument is an entity, the class '{1}' must be specified in the orm.xml or annotated with @Entity and must be in the scope of a persistence unit.",
2834:                                                operation, className));
2835:                    }
2836:                }
2837:
2838:                return (Entity) entity;
2839:            }
2840:
2841:            /**
2842:             * Detach after non-xa.
2843:             */
2844:            public void detach() {
2845:                if (_isXA || _isInTransaction)
2846:                    throw new IllegalStateException(L
2847:                            .l("detach cannot be called within transaction"));
2848:
2849:                _completionList.clear();
2850:
2851:                _txEntitiesTop = 0;
2852:
2853:                // jpa/1700
2854:                for (int i = _entitiesTop - 1; i >= 0; i--) {
2855:                    _entities[i].__caucho_detach();
2856:                }
2857:
2858:                // jpa/0o0d
2859:                _entitiesTop = 0;
2860:            }
2861:
2862:            /**
2863:             * Flush managed entities.
2864:             */
2865:            private void flushInternal() throws Exception {
2866:                // Do not flush within merge() or while loading an entity.
2867:                if (!_isFlushAllowed)
2868:                    return;
2869:
2870:                /* XXX: moved into __caucho_flush
2871:                   for (int i = _txEntities.size() - 1; i >= 0; i--) {
2872:                     Entity entity = _txEntities.get(i);
2873:
2874:                     EntityState state = entity.__caucho_getEntityState();
2875:
2876:                     // jpa/0i60
2877:                     // jpa/0h27: for all entities Y referenced by a *managed*
2878:                     // entity X, where the relationship has been annotated
2879:                     // with cascade=PERSIST/ALL, the persist operation is
2880:                     // applied to Y. It is a lazy cascade as the relationship
2881:                     // is not always initialized at the time persist(X) was
2882:                     // called but must be at flush time.
2883:
2884:                     if (state == EntityState.P_PERSIST) {
2885:                       entity.__caucho_cascadePrePersist(this);
2886:                       entity.__caucho_cascadePostPersist(this);
2887:                     }
2888:                   }
2889:                 */
2890:
2891:                // We avoid breaking FK constraints:
2892:                //
2893:                // 1. Assume _txEntities has the following order: A <- B <- C
2894:                //    XXX: Make sure priorities are handled based on owning sides
2895:                //    even when there are cycles in a graph.
2896:                //
2897:                // 2. Persist is done in ascending order: A(0) <- B(1) <- C(2)
2898:                //
2899:                // 3. Delete is done in descending order: C(2) -> B(1) -> A(0)
2900:                // Persists in ascending order.
2901:                for (int i = 0; i < _txEntitiesTop; i++) {
2902:                    Entity entity = _txEntities[i];
2903:
2904:                    if (entity.__caucho_getEntityState().isPersist()) {
2905:                        try {
2906:                            entity.__caucho_flush();
2907:                        } catch (SQLException e) {
2908:                            log.log(Level.FINER, e.toString(), e);
2909:
2910:                            String sqlState = e.getSQLState();
2911:
2912:                            JdbcMetaData metaData = _persistenceUnit
2913:                                    .getMetaData();
2914:
2915:                            if (metaData.isUniqueConstraintSQLState(sqlState)) {
2916:                                // jpa/0ga5
2917:                                throw new EntityExistsException(
2918:                                        L
2919:                                                .l(
2920:                                                        "Trying to persist an entity of class '{0}' with PK '{1}' that already exists. Entity state '{2}'",
2921:                                                        entity.getClass()
2922:                                                                .getName(),
2923:                                                        entity
2924:                                                                .__caucho_getPrimaryKey(),
2925:                                                        entity
2926:                                                                .__caucho_getEntityState()));
2927:                            } else if (metaData
2928:                                    .isForeignKeyViolationSQLState(sqlState)) {
2929:                                // jpa/0o42
2930:                                throw new IllegalStateException(
2931:                                        L
2932:                                                .l(
2933:                                                        "Trying to persist an entity of class '{0}' with PK '{1}' would break a foreign key constraint. The entity state is '{2}'. Please make sure there are associated entities for all required relationships. If you are merging an entity make sure the association fields are annotated with cascade=MERGE or cascade=ALL.",
2934:                                                        entity.getClass()
2935:                                                                .getName(),
2936:                                                        entity
2937:                                                                .__caucho_getPrimaryKey(),
2938:                                                        entity
2939:                                                                .__caucho_getEntityState()));
2940:                            }
2941:
2942:                            throw e;
2943:                        }
2944:                    }
2945:                }
2946:
2947:                // jpa/0h25
2948:                // Deletes in descending order.
2949:                for (int i = _txEntitiesTop - 1; i >= 0; i--) {
2950:                    Entity entity = _txEntities[i];
2951:
2952:                    if (!entity.__caucho_getEntityState().isPersist())
2953:                        entity.__caucho_flush();
2954:                }
2955:
2956:                if (!isInTransaction()) {
2957:                    if (_completionList.size() > 0) {
2958:                        _persistenceUnit.complete(_completionList);
2959:                    }
2960:                    _completionList.clear();
2961:
2962:                    for (int i = 0; i < _txEntitiesTop; i++) {
2963:                        Entity entity = _txEntities[i];
2964:
2965:                        entity.__caucho_afterCommit();
2966:                    }
2967:
2968:                    _txEntitiesTop = 0;
2969:                }
2970:            }
2971:
2972:            /**
2973:             * Persists the entity.
2974:             */
2975:            private void persistInternal(Entity entity) throws Exception {
2976:                EntityState state = entity.__caucho_getEntityState();
2977:
2978:                switch (state) {
2979:                case TRANSIENT: {
2980:                    Entity contextEntity = getEntity(entity.getClass()
2981:                            .getName(), entity.__caucho_getPrimaryKey());
2982:
2983:                    // jpa/0ga3
2984:                    if (contextEntity != null) {
2985:                        if (contextEntity.__caucho_getEntityState().ordinal() == EntityState.P_DELETED
2986:                                .ordinal()) {
2987:                            // jpa/0ga3
2988:                            contextEntity.__caucho_flush();
2989:                        } else if (entity != contextEntity) {
2990:                            // jpa/0ga1: trying to persist a detached entity that already exists.
2991:                            throw new EntityExistsException(
2992:                                    L
2993:                                            .l(
2994:                                                    "Trying to persist a detached entity of class '{0}' with PK '{1}' that already exists. Entity state '{2}'",
2995:                                                    entity.getClass().getName(),
2996:                                                    entity
2997:                                                            .__caucho_getPrimaryKey(),
2998:                                                    state));
2999:                        }
3000:                    }
3001:
3002:                    // jpa/0h24
3003:                    // Pre-persist child entities.
3004:                    entity.__caucho_cascadePrePersist(this );
3005:
3006:                    createInternal(entity);
3007:                }
3008:                    break;
3009:
3010:                case P_DELETING:
3011:                case P_DELETED: {
3012:                    // jpa/0i60, jpa/1510, jpa/0h25
3013:                    // jpa/0h26
3014:                    entity.__caucho_cascadePrePersist(this );
3015:
3016:                    // removed entity instance, reset state and persist.
3017:                    entity.__caucho_makePersistent(null, (EntityType) null);
3018:                    createInternal(entity);
3019:                }
3020:                    break;
3021:
3022:                case P_PERSISTING:
3023:                case P_PERSISTED: {
3024:                    // jpa/0h26
3025:                    // Pre-persist child entities.
3026:                    entity.__caucho_cascadePrePersist(this );
3027:                }
3028:                    break;
3029:
3030:                default:
3031:                    if (entity.__caucho_getConnection() == this )
3032:                        return;
3033:                    else {
3034:                        // jpa/0ga5 (tck):
3035:                        // See entitytest.persist.basic.persistBasicTest4 vs.
3036:                        //     callback.inheritance.preUpdateTest
3037:                        throw new EntityExistsException(
3038:                                L
3039:                                        .l(
3040:                                                "Trying to persist an entity that is detached or already exists. Entity state '{0}'",
3041:                                                state));
3042:                    }
3043:                }
3044:
3045:                // jpa/0j5e
3046:                updateFlushPriority(entity);
3047:
3048:                // jpa/0h27, jpa/0i5c, jpa/0j5g
3049:                // Post-persist child entities.
3050:                entity.__caucho_cascadePostPersist(this );
3051:            }
3052:
3053:            /**
3054:             * Updates flush priorities.
3055:             */
3056:            private void updateFlushPriority(Entity updateEntity) {
3057:                if (!isActiveTransaction())
3058:                    return;
3059:
3060:                removeTxEntity(updateEntity);
3061:
3062:                int updatePriority = updateEntity.__caucho_getEntityType()
3063:                        .getFlushPriority();
3064:
3065:                for (int i = _txEntitiesTop - 1; i >= 0; i--) {
3066:                    Entity entity = _txEntities[i];
3067:
3068:                    int currentPriority = entity.__caucho_getEntityType()
3069:                            .getFlushPriority();
3070:
3071:                    if (currentPriority < updatePriority) {
3072:                        addTxEntity(i + 1, updateEntity);
3073:                        return;
3074:                    }
3075:                }
3076:
3077:                addTxEntity(0, updateEntity);
3078:            }
3079:
3080:            /**
3081:             * Recursively merges the state of the entity into the current context.
3082:             */
3083:            public <T> T recursiveMerge(T entityT) {
3084:                // jpa/0ga3, jpa/0h08, jpa/0i5g, jpa/0s2k
3085:
3086:                try {
3087:                    if (entityT == null)
3088:                        return null;
3089:
3090:                    Entity entity = checkEntityType(entityT, "merge");
3091:
3092:                    if (log.isLoggable(Level.FINER)) {
3093:                        String className = entity.getClass().getName();
3094:                        Object pk = entity.__caucho_getPrimaryKey();
3095:                        EntityState state = entity.__caucho_getEntityState();
3096:
3097:                        log
3098:                                .log(
3099:                                        Level.FINER,
3100:                                        L
3101:                                                .l(
3102:                                                        "recursiveMerge(class: '{0}' PK: '{1}' state: '{2}')",
3103:                                                        className, pk, state));
3104:                    }
3105:
3106:                    Entity managedEntity = null;
3107:
3108:                    if (containsMergingEntity(entity))
3109:                        managedEntity = entity;
3110:                    else
3111:                        managedEntity = mergeDetachedEntity(entity, true);
3112:
3113:                    return (T) managedEntity;
3114:
3115:                } catch (RuntimeException e) {
3116:                    throw e;
3117:                } catch (Exception e) {
3118:                    throw new EJBExceptionWrapper(e);
3119:                }
3120:            }
3121:
3122:            public Entity mergeDetachedEntity(Entity entity, boolean isFullMerge) {
3123:                try {
3124:                    if (entity == null)
3125:                        return entity;
3126:
3127:                    String className = entity.getClass().getName();
3128:                    EntityState state = entity.__caucho_getEntityState();
3129:
3130:                    Object pk = entity.__caucho_getPrimaryKey();
3131:
3132:                    if (log.isLoggable(Level.FINER))
3133:                        log.log(Level.FINER, L.l(
3134:                                "merge(class: '{0}' PK: '{1}' state: '{2}')",
3135:                                className, pk, state));
3136:
3137:                    if (EntityState.P_DELETING.ordinal() <= state.ordinal()) {
3138:                        // removed entity instance
3139:                        throw new IllegalArgumentException(
3140:                                L
3141:                                        .l("Merge operation cannot be applied to a removed entity instance"));
3142:                    }
3143:
3144:                    Entity managedEntity = null;
3145:
3146:                    // XXX: jpa/0o42 try {
3147:
3148:                    Entity existingEntity = null;
3149:
3150:                    try {
3151:                        boolean isManaged = entity.__caucho_getEntityState()
3152:                                .isManaged();
3153:
3154:                        existingEntity = (Entity) load(entity.getClass(), pk,
3155:                                true);
3156:                    } catch (AmberObjectNotFoundException e) {
3157:                        if (log.isLoggable(Level.FINER))
3158:                            log.log(Level.FINER, e.toString(), e);
3159:                        // JPA: should not throw at all, returns null only.
3160:                    }
3161:
3162:                    // XXX: the original entity should remain detached jpa/0s2k
3163:                    // setTransactionalState(entity);
3164:
3165:                    if (existingEntity == null) {
3166:                        // new entity instance
3167:                        managedEntity = addNewEntity(entity.getClass(), pk);
3168:
3169:                        if (managedEntity == null)
3170:                            throw new IllegalStateException(
3171:                                    L
3172:                                            .l(
3173:                                                    "Unable to add a new managed entity when merging object class: {0} PK: {1}.",
3174:                                                    className, pk));
3175:                    } else {
3176:                        // jpa/0h08
3177:                        managedEntity = existingEntity;
3178:                    }
3179:
3180:                    int index = getEntityMatch(_mergingEntities, className, pk);
3181:
3182:                    if (index >= 0) {
3183:                        // jpa/0o42
3184:                        managedEntity = _mergingEntities.get(index);
3185:                    } else {
3186:                        _mergingEntities.add(managedEntity);
3187:
3188:                        if (isFullMerge) {
3189:                            // jpa/0o42: avoids premature loading.
3190:                            managedEntity.__caucho_setConnection(null);
3191:
3192:                            entity.__caucho_copyTo(managedEntity, this , true);
3193:
3194:                            // jpa/0o42
3195:                            managedEntity.__caucho_setConnection(this );
3196:                        }
3197:
3198:                        if (existingEntity == null) {
3199:                            // jpa/0o42
3200:
3201:                            // cascade children
3202:                            // XXX: called from persist()
3203:                            // entity.__caucho_cascadePrePersist(this);
3204:
3205:                            // jpa/0o42
3206:                            managedEntity.__caucho_setConnection(null);
3207:                            managedEntity
3208:                                    .__caucho_setEntityState(EntityState.TRANSIENT);
3209:
3210:                            persist(managedEntity);
3211:
3212:                            // jpa/0i5g
3213:                            // XXX: called from persist()
3214:                            // entity.__caucho_cascadePostPersist(this);
3215:
3216:                            if (log.isLoggable(Level.FINER))
3217:                                log
3218:                                        .log(
3219:                                                Level.FINER,
3220:                                                L
3221:                                                        .l("merged to a new entity (persisted)"));
3222:                        } else {
3223:                            // Handled in addInternalEntity()
3224:                            // setTransactionalState(managedEntity);
3225:
3226:                            if (log.isLoggable(Level.FINER))
3227:                                log.log(Level.FINER, L
3228:                                        .l("merged to an existing entity"));
3229:                        }
3230:
3231:                        // jpa/0o42: avoids premature loading.
3232:                        managedEntity.__caucho_setConnection(null);
3233:
3234:                        // jpa/0ga3, jpa/0h08, jpa/0o4-
3235:                        entity.__caucho_merge(managedEntity, this , false);
3236:
3237:                        // jpa/0o42
3238:                        managedEntity.__caucho_setConnection(this );
3239:
3240:                        // jpa/0h08
3241:                        entity.__caucho_copyDirtyMaskFrom(managedEntity);
3242:                        entity.__caucho_copyLoadMaskFrom(managedEntity);
3243:                    }
3244:
3245:                    /* XXX: jpa/0o42
3246:                       } catch (Exception e) {
3247:                         if (e.getCause() instanceof SQLException) {
3248:                           // OK: entity exists in the database
3249:                           log.log(Level.FINER, e.toString(), e);
3250:                         }
3251:                         else {
3252:                           throw e;
3253:                         }
3254:                       }
3255:                     */
3256:
3257:                    return managedEntity;
3258:
3259:                } catch (RuntimeException e) {
3260:                    throw e;
3261:                } catch (Exception e) {
3262:                    throw new EJBExceptionWrapper(e);
3263:                }
3264:            }
3265:
3266:            /**
3267:             * Creates an instance of the named query
3268:             */
3269:            private Query createInternalNativeQuery(String sql) {
3270:                try {
3271:                    QueryImpl query = new QueryImpl(this );
3272:
3273:                    query.setNativeSql(sql);
3274:
3275:                    return query;
3276:                } catch (RuntimeException e) {
3277:                    throw new IllegalArgumentException(e);
3278:                } catch (Exception e) {
3279:                    throw new EJBExceptionWrapper(e);
3280:                }
3281:            }
3282:
3283:            /**
3284:             * Creates an instance of the native query.
3285:             */
3286:            private Query createInternalNativeQuery(String sql,
3287:                    SqlResultSetMappingConfig map) {
3288:                Query query = createInternalNativeQuery(sql);
3289:
3290:                QueryImpl queryImpl = (QueryImpl) query;
3291:
3292:                queryImpl.setSqlResultSetMapping(map);
3293:
3294:                return query;
3295:            }
3296:
3297:            private boolean containsMergingEntity(Entity entity) {
3298:                if (_mergingEntities.contains(entity))
3299:                    return true;
3300:
3301:                // jpa/0o42
3302:                int index = getEntityMatch(_mergingEntities, entity.getClass()
3303:                        .getName(), entity.__caucho_getPrimaryKey());
3304:
3305:                return (index >= 0);
3306:            }
3307:
3308:            public void addEntity(Entity entity) {
3309:                Entity[] entities = _entities;
3310:
3311:                if (_entitiesTop == entities.length) {
3312:                    entities = new Entity[_entities.length + 32];
3313:                    System.arraycopy(_entities, 0, entities, 0,
3314:                            _entities.length);
3315:                    _entities = entities;
3316:                }
3317:
3318:                entities[_entitiesTop++] = entity;
3319:            }
3320:
3321:            private void removeEntityImpl(Entity entity) {
3322:                Entity[] entities = _entities;
3323:
3324:                for (int i = _entitiesTop - 1; i >= 0; i--) {
3325:                    if (entities[i] == entity) {
3326:                        System.arraycopy(entities, i + 1, entities, i,
3327:                                _entitiesTop - i - 1);
3328:
3329:                        _entitiesTop -= 1;
3330:
3331:                        return;
3332:                    }
3333:                }
3334:            }
3335:
3336:            private void addTxEntity(Entity entity) {
3337:                Entity[] entities = _txEntities;
3338:
3339:                if (_txEntitiesTop == entities.length) {
3340:                    entities = new Entity[entities.length + 32];
3341:                    System.arraycopy(_txEntities, 0, entities, 0,
3342:                            _txEntities.length);
3343:                    _txEntities = entities;
3344:                }
3345:
3346:                entities[_txEntitiesTop++] = entity;
3347:            }
3348:
3349:            private void removeTxEntity(Entity entity) {
3350:                Entity[] entities = _txEntities;
3351:
3352:                for (int i = _txEntitiesTop - 1; i >= 0; i--) {
3353:                    if (entities[i] == entity) {
3354:                        System.arraycopy(entities, i + 1, entities, i,
3355:                                _txEntitiesTop - i - 1);
3356:
3357:                        _txEntitiesTop -= 1;
3358:
3359:                        return;
3360:                    }
3361:                }
3362:            }
3363:
3364:            private void addTxEntity(int index, Entity entity) {
3365:                Entity[] entities = _txEntities;
3366:
3367:                if (_txEntitiesTop == entities.length) {
3368:                    entities = new Entity[_txEntities.length + 32];
3369:                    System.arraycopy(_txEntities, 0, entities, 0,
3370:                            _txEntities.length);
3371:                    _txEntities = entities;
3372:                }
3373:
3374:                if (index < _txEntitiesTop)
3375:                    System.arraycopy(entities, index, entities, index + 1,
3376:                            _txEntitiesTop - index);
3377:
3378:                entities[index] = entity;
3379:
3380:                _txEntitiesTop += 1;
3381:            }
3382:
3383:            private static int getEntityMatch(ArrayList<Entity> list,
3384:                    String className, Object key) {
3385:                // See also: getEntity() and getTransactionEntity().
3386:
3387:                // jpa/0o42
3388:                for (int i = list.size() - 1; i >= 0; i--) {
3389:                    Entity entity = list.get(i);
3390:
3391:                    if (entity.__caucho_match(className, key)) {
3392:                        return i;
3393:                    }
3394:                }
3395:
3396:                return -1;
3397:            }
3398:
3399:            private class EntityTransactionImpl implements  EntityTransaction {
3400:                private boolean _rollbackOnly;
3401:
3402:                /**
3403:                 * Starts a resource transaction.
3404:                 */
3405:                public void begin() {
3406:                    // jpa/1522
3407:                    if (isActiveTransaction())
3408:                        throw new IllegalStateException(
3409:                                "begin() cannot be called when the entity transaction is already active.");
3410:
3411:                    _rollbackOnly = false;
3412:
3413:                    try {
3414:                        AmberConnection.this .beginTransaction();
3415:                    } catch (SQLException e) {
3416:                        throw new PersistenceException(e);
3417:                    }
3418:                }
3419:
3420:                /**
3421:                 * Commits a resource transaction.
3422:                 */
3423:                public void commit() {
3424:                    // jpa/1523
3425:                    if (!isActiveTransaction())
3426:                        throw new IllegalStateException(
3427:                                "commit() cannot be called when the entity transaction is not active.");
3428:
3429:                    // jpa/1525
3430:                    if (getRollbackOnly())
3431:                        throw new RollbackException(
3432:                                "commit() cannot be called when the entity transaction is marked for rollback only.");
3433:
3434:                    try {
3435:                        // jpa/11a7
3436:                        AmberConnection.this .beforeCommit();
3437:
3438:                        _isInTransaction = false;
3439:
3440:                        // jpa/11a7 AmberConnection.this.commit();
3441:                        if (AmberConnection.this ._conn != null) {
3442:                            AmberConnection.this ._conn.commit();
3443:                        }
3444:
3445:                        // XXX: missing finally issues if _conn.commit fails
3446:
3447:                        // jpa/11a7
3448:                        AmberConnection.this .afterCommit(true);
3449:
3450:                        if (AmberConnection.this ._conn != null) {
3451:                            closeConnectionImpl();
3452:                        }
3453:                    } catch (SQLException e) {
3454:                        throw new PersistenceException(e);
3455:                    }
3456:                }
3457:
3458:                /**
3459:                 * Rolls the current transaction back.
3460:                 */
3461:                public void rollback() {
3462:                    // jpa/1524
3463:                    if (!isActiveTransaction())
3464:                        throw new IllegalStateException(
3465:                                "rollback() cannot be called when the entity transaction is not active.");
3466:
3467:                    setRollbackOnly();
3468:
3469:                    PersistenceException exn = null;
3470:
3471:                    try {
3472:                        AmberConnection.this .rollback();
3473:                    } catch (Exception e) {
3474:                        exn = new PersistenceException(e);
3475:                    } finally {
3476:                        try {
3477:                            // jpa/1501
3478:                            AmberConnection.this .afterCommit(false);
3479:                        } catch (PersistenceException e) {
3480:                            exn = e;
3481:                        } catch (Exception e) {
3482:                            exn = new PersistenceException(e);
3483:                        } finally {
3484:                            // jpa/1525
3485:                            if (AmberConnection.this ._conn != null) {
3486:                                closeConnectionImpl();
3487:                            }
3488:                        }
3489:                    }
3490:
3491:                    if (exn != null)
3492:                        throw exn;
3493:                }
3494:
3495:                /**
3496:                 * Marks the current transaction for rollback only.
3497:                 */
3498:                public void setRollbackOnly() {
3499:                    // jpa/1521
3500:                    if (!isActiveTransaction())
3501:                        throw new IllegalStateException(
3502:                                "setRollbackOnly() cannot be called when the entity transaction is not active.");
3503:
3504:                    _rollbackOnly = true;
3505:                }
3506:
3507:                /**
3508:                 * Returns true if the transaction is for rollback only.
3509:                 */
3510:                public boolean getRollbackOnly() {
3511:                    // jpa/1520
3512:                    if (!isActiveTransaction())
3513:                        throw new IllegalStateException(
3514:                                "getRollbackOnly() cannot be called when the entity transaction is not active.");
3515:
3516:                    return _rollbackOnly;
3517:                }
3518:
3519:                /**
3520:                 * Test if a transaction is in progress.
3521:                 */
3522:                public boolean isActive() {
3523:                    return _isInTransaction;
3524:                }
3525:            }
3526:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.