Source Code Cross Referenced for VersantPersistenceManagerImp.java in  » Testing » PolePosition-0.20 » com » versant » core » jdo » 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 » Testing » PolePosition 0.20 » com.versant.core.jdo 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998 - 2005 Versant Corporation
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         * Versant Corporation - initial API and implementation
0010:         */
0011:        package com.versant.core.jdo;
0012:
0013:        import com.versant.core.common.Debug;
0014:        import com.versant.core.common.*;
0015:        import com.versant.core.jdo.sco.VersantSCOCollection;
0016:        import com.versant.core.metadata.*;
0017:        import com.versant.core.jdo.query.mem.MemQueryCompiler;
0018:
0019:        import javax.jdo.*;
0020:        import javax.jdo.spi.JDOImplHelper;
0021:        import javax.jdo.spi.PersistenceCapable;
0022:        import javax.jdo.spi.StateManager;
0023:
0024:        import javax.transaction.Status;
0025:        import javax.transaction.Synchronization;
0026:        import javax.transaction.xa.XAException;
0027:        import javax.transaction.xa.XAResource;
0028:        import javax.transaction.xa.Xid;
0029:
0030:        import java.lang.reflect.Modifier;
0031:        import java.lang.ref.Reference;
0032:        import java.sql.Connection;
0033:        import java.util.*;
0034:
0035:        import com.versant.core.common.BindingSupportImpl; //import com.versant.core.vds.util.Loid;
0036:        import com.versant.core.storagemanager.StorageManager;
0037:        import com.versant.core.storagemanager.ApplicationContext;
0038:
0039:        /**
0040:         * This is a global StateManager instance for a PersistenceManagerImp. It will
0041:         * assign a state managing object to a managed PersistenceCapable instance.
0042:         */
0043:        public final class VersantPersistenceManagerImp implements 
0044:                VersantPersistenceManager, ApplicationContext, Transaction,
0045:                PersistenceContext, XAResource, Synchronization {
0046:
0047:            /**
0048:             * Double linked list of dirty instances.
0049:             *
0050:             * @see PCStateMan#next
0051:             * @see PCStateMan#prev
0052:             */
0053:            private PCStateMan txDirtyListHead;
0054:            private PCStateMan txDirtyListTail;
0055:
0056:            public VersantPersistenceManagerImp prev;
0057:            public VersantPersistenceManagerImp next;
0058:            public boolean idle;
0059:
0060:            /**
0061:             * The list of instances that has been marked for delete in the current tx.
0062:             */
0063:            private final DeletePacket toBeDeleted;
0064:            /**
0065:             * This is used to transport the dirty stuff to the server.
0066:             */
0067:            public final StatesToStore storeOidStateContainer;
0068:            /**
0069:             * while busy with a retrieve graph this will be set to true
0070:             */
0071:            private boolean retrieveing;
0072:            /**
0073:             * This is the instances that has been retrieved already.
0074:             */
0075:            private final Set retrieveSet = new HashSet();
0076:
0077:            /**
0078:             * The user object set by a client.
0079:             */
0080:            private Object userObject;
0081:
0082:            /**
0083:             * A Transaction may be associated with an Synchronization instance. If so this will be set to
0084:             * the supplied intstance
0085:             *
0086:             * @see #setSynchronization
0087:             */
0088:
0089:            private Synchronization synchronizationInstance;
0090:
0091:            /**
0092:             * This is a cheat to quickly get the sm for a pc instance.
0093:             * When getPM is called on the stateManager it sets itself to the
0094:             */
0095:            public PCStateMan requestedPCState;
0096:            public final ModelMetaData modelMetaData;
0097:            private LocalPMCache cache;
0098:            public final JDOImplHelper jdoImplHelper = JDOImplHelper
0099:                    .getInstance();
0100:
0101:            /**
0102:             * Indication if tx is active.
0103:             */
0104:            private boolean transactionActive;
0105:            private boolean busyWithRollback;
0106:
0107:            /**
0108:             * The counter that is used in creating NewObjectOID.
0109:             */
0110:            private int counter = 0;
0111:
0112:            private boolean retainValues;
0113:            private boolean restoreValues;
0114:            private boolean optimistic;
0115:            private boolean nontransactionalRead;
0116:            private boolean nontransactionalWrite;
0117:            private boolean ignoreCache;
0118:            private boolean multithreaded;
0119:
0120:            /**
0121:             * If PersistenceManager is closed.
0122:             */
0123:            private boolean closed;
0124:
0125:            /**
0126:             * The factory that created this pm.
0127:             */
0128:            private final VersantPMFInternal pmf;
0129:
0130:            private final MemQueryCompiler memQueryCompiler;
0131:
0132:            /**
0133:             * This will force the instance to be thrown away by the pool.
0134:             */
0135:            private boolean mustNotPool;
0136:            private boolean inPool;
0137:
0138:            /**
0139:             * This is the proxy that is used for all client access.
0140:             * This is used to decouple us from any instances left lying around.
0141:             * This proxy ref must be reset to a new instance every time that it
0142:             * is taken from the pool to be given out to a client.
0143:             */
0144:            private PMProxy proxy;
0145:
0146:            /**
0147:             * This is a bitset of all dirty classes.
0148:             */
0149:            private final CmdBitSet dirtyCmdBits;
0150:            private final StorageManager sm;
0151:
0152:            /**
0153:             * This variable is used to control the strict adherence to the spec. when
0154:             * transaction commits. If false then instances read in the tx but which is
0155:             * p-nontx will be hollowed.
0156:             */
0157:            private boolean strict;
0158:            private boolean interceptDfgFieldAccess = true;
0159:
0160:            private boolean checkModelConsistencyOnCommit;
0161:
0162:            public static final String LANGUAGE_SQL = "SQL";
0163:            public static final String LANGUAGE_EJBQL = "EJBQL";
0164:
0165:            // These fields keep track of OIDs/instances of objectid-class'es and
0166:            // classes to evict from l2 cache if the transaction commits (epc = Evict
0167:            // Post Commit).
0168:            private Object[] epcObjects;
0169:            private int epcObjectCount;
0170:            private int[] epcClasses;
0171:            private int epcClassCount;
0172:            private boolean[] epcClassPresent;
0173:            private boolean epcAll;
0174:
0175:            private LifecycleListenerManager listeners;
0176:
0177:            private Reference activeReference;
0178:
0179:            public VersantPersistenceManagerImp(VersantPMFInternal pmf,
0180:                    ModelMetaData modelMetaData, StorageManager sm,
0181:                    LocalPMCache jdoManagedCache,
0182:                    MemQueryCompiler memQueryCompiler) {
0183:                this .pmf = pmf;
0184:                this .modelMetaData = modelMetaData;
0185:                this .sm = sm;
0186:                this .storeOidStateContainer = new StatesToStore(modelMetaData);
0187:                this .toBeDeleted = new DeletePacket(modelMetaData);
0188:                dirtyCmdBits = new CmdBitSet(modelMetaData);
0189:                this .cache = jdoManagedCache;
0190:                this .cache.setPm(this );
0191:                this .memQueryCompiler = memQueryCompiler;
0192:            }
0193:
0194:            private void createProxy() {
0195:                if (multithreaded) {
0196:                    proxy = new SynchronizedPMProxy(this );
0197:                } else {
0198:                    proxy = new UnsynchronizedPMProxy(this );
0199:                }
0200:            }
0201:
0202:            public boolean isInterceptDfgFieldAccess() {
0203:                return interceptDfgFieldAccess;
0204:            }
0205:
0206:            public void setInterceptDfgFieldAccess(boolean on) {
0207:                if (interceptDfgFieldAccess == on)
0208:                    return;
0209:                cache.setInterceptDfgFieldAccess(interceptDfgFieldAccess = on);
0210:            }
0211:
0212:            public boolean isStrict() {
0213:                return strict;
0214:            }
0215:
0216:            public void setStrict(boolean strict) {
0217:                this .strict = strict;
0218:            }
0219:
0220:            public PMProxy getProxy() {
0221:                return proxy;
0222:            }
0223:
0224:            public boolean isInPool() {
0225:                return inPool;
0226:            }
0227:
0228:            public void setMustNotPool(boolean mustNotPool) {
0229:                this .mustNotPool = mustNotPool;
0230:            }
0231:
0232:            public boolean isMustNotPool() {
0233:                return mustNotPool;
0234:            }
0235:
0236:            /**
0237:             * This is called by the pool instance the moment comes in or out of the
0238:             * pool.
0239:             */
0240:            public void setInPool(boolean inPool) {
0241:                this .inPool = inPool;
0242:                if (inPool) {
0243:                    proxy = null;
0244:                } else {
0245:                    createProxy();
0246:                    if (managed)
0247:                        managedClosed = false;
0248:                }
0249:            }
0250:
0251:            /**
0252:             * Reset the proxy so that if a client has a weak/soft ref to pm he will
0253:             * get a closed exception. Then return us to our PMF.
0254:             */
0255:            protected void finalize() throws Throwable {
0256:                boolean txWasActive = transactionActive;
0257:                if (transactionActive) {
0258:                    rollback();
0259:                }
0260:                proxy.resetPM();
0261:                pmf.pmClosedNotification(this , true, txWasActive);
0262:            }
0263:
0264:            /**
0265:             * Sets the master on the detail in a Master/Detail relationship. If
0266:             * removeFromCurrentMaster is true then the detail is removed from its
0267:             * current master (if any and if different).
0268:             */
0269:            public void setMasterOnDetail(PersistenceCapable detail,
0270:                    int managedFieldNo, PersistenceCapable master,
0271:                    boolean removeFromCurrentMaster) {
0272:                getInternalSM(detail).setMaster(managedFieldNo, master,
0273:                        removeFromCurrentMaster);
0274:            }
0275:
0276:            /**
0277:             * Get a collection field from a pc. This is used to implement many-to-many
0278:             * relationships.
0279:             */
0280:            public VersantSCOCollection getCollectionField(
0281:                    PersistenceCapable pc, int fieldNo) {
0282:                PCStateMan sm = getInternalSM(pc);
0283:                return (VersantSCOCollection) sm.getObjectField(null, fieldNo,
0284:                        null);
0285:            }
0286:
0287:            public Object getObjectField(PersistenceCapable pc, int fieldNo) {
0288:                PCStateMan sm = getInternalSM(pc);
0289:                return sm.getObjectField(null, fieldNo, null);
0290:            }
0291:
0292:            public String getConnectionURL(String dataStore) {
0293:                try {
0294:                    return pmf.getConnectionURL();
0295:                } catch (Exception e) {
0296:                    handleException(e);
0297:                    return null;
0298:                }
0299:            }
0300:
0301:            public void cancelQueryExecution() {
0302:                // todo implement jdoConnection.cancelQueryExecution();
0303:            }
0304:
0305:            public String getConnectionDriverName(String dataStore) {
0306:                try {
0307:                    return pmf.getConnectionDriverName();
0308:                } catch (Exception e) {
0309:                    handleException(e);
0310:                    return null;
0311:                }
0312:            }
0313:
0314:            public Connection getJdbcConnection(String datastore) {
0315:                if (!transactionActive) {
0316:                    throw BindingSupportImpl
0317:                            .getInstance()
0318:                            .invalidOperation(
0319:                                    "A JDBC Connection may only be obtained within a active JDO transaction.");
0320:                }
0321:                try {
0322:                    return (Connection) sm.getDatastoreConnection();
0323:                } catch (Exception e) {
0324:                    handleException(e);
0325:                    return null;
0326:                }
0327:            }
0328:
0329:            /**
0330:             *
0331:             */
0332:            public void flushIfDepOn(int[] cmdBits) {
0333:                if (cmdBits != null && dirtyCmdBits.containsAny(cmdBits))
0334:                    flushRetainState();
0335:            }
0336:
0337:            public void loadFetchGroup(Object pc, String name) {
0338:                try {
0339:                    if (!(pc instanceof  PersistenceCapable)) {
0340:                        String msg;
0341:                        if (pc == null) {
0342:                            msg = "Instance is null";
0343:                        } else {
0344:                            msg = "Instance is not a persistence class: "
0345:                                    + pc.getClass().getName();
0346:                        }
0347:                        throw BindingSupportImpl.getInstance().runtime(msg);
0348:                    }
0349:                    PCStateMan sm = getInternalSM((PersistenceCapable) pc);
0350:                    if (sm == null) {
0351:                        throw BindingSupportImpl.getInstance()
0352:                                .invalidOperation(
0353:                                        "Instance is not managed by JDO (it is transient): "
0354:                                                + Utils.toString(pc));
0355:                    }
0356:                    sm.loadFetchGroup(name);
0357:                } catch (RuntimeException e) {
0358:                    handleException(e);
0359:                }
0360:            }
0361:
0362:            public boolean isRetainValues() {
0363:                return retainValues;
0364:            }
0365:
0366:            public boolean isRestoreValues() {
0367:                return restoreValues;
0368:            }
0369:
0370:            public boolean isOptimistic() {
0371:                return optimistic;
0372:            }
0373:
0374:            public boolean isNontransactionalRead() {
0375:                return nontransactionalRead;
0376:            }
0377:
0378:            public boolean isNontransactionalWrite() {
0379:                return nontransactionalWrite;
0380:            }
0381:
0382:            public boolean isIgnoreCache() {
0383:                return ignoreCache;
0384:            }
0385:
0386:            public void evict(Object pc) {
0387:                try {
0388:                    if (pc == null)
0389:                        return;
0390:                    PersistenceCapable persistenceCapable = checkPersCapable(pc);
0391:                    PersistenceManager pm = persistenceCapable
0392:                            .jdoGetPersistenceManager();
0393:                    // This instance is not managed. So return.
0394:                    if (pm == null)
0395:                        return;
0396:                    checkPM(pm, proxy);
0397:                    getInternalSM(persistenceCapable).evict();
0398:                } catch (Exception e) {
0399:                    handleException(e);
0400:                }
0401:            }
0402:
0403:            public void evictAll() {
0404:                try {
0405:                    cache.evict();
0406:                } catch (Exception e) {
0407:                    handleException(e);
0408:                }
0409:            }
0410:
0411:            public void evictAll(Object[] pcs) {
0412:                for (int i = pcs.length - 1; i >= 0; i--) {
0413:                    evict(pcs[i]);
0414:                }
0415:            }
0416:
0417:            public void evictAll(Collection pcs) {
0418:                try {
0419:                    Object[] persistenceCapables = new Object[pcs.size()];
0420:                    pcs.toArray(persistenceCapables);
0421:                    for (int i = persistenceCapables.length - 1; i >= 0; i--) {
0422:                        evict(persistenceCapables[i]);
0423:                    }
0424:                } catch (Exception e) {
0425:                    handleException(e);
0426:                }
0427:            }
0428:
0429:            public Object getObjectId(Object pc) {
0430:                try {
0431:                    if (pc == null) {
0432:                        throw BindingSupportImpl.getInstance()
0433:                                .invalidOperation(
0434:                                        "The supplied Object param is null");
0435:                    }
0436:
0437:                    if (!(pc instanceof  PersistenceCapable))
0438:                    // pmPreCheck throws exception in this case
0439:                    {
0440:                        return null;
0441:                    }
0442:
0443:                    PCStateMan pcStateObject = pmPreCheck(pc);
0444:                    if (pcStateObject != null) {
0445:                        return pcStateObject.getObjectId(null);
0446:                    } else {
0447:                        return null;
0448:                    }
0449:                } catch (RuntimeException e) {
0450:                    handleException(e);
0451:                    return null;
0452:                }
0453:            }
0454:
0455:            public Object getExternalOID(OID oid) {
0456:                PCStateMan sm = cache.getByOID(oid, false);
0457:                if (sm != null) {
0458:                    return sm.getObjectId(null);
0459:                } else {
0460:                    ClassMetaData classMetaData = oid
0461:                            .getAvailableClassMetaData();
0462:                    if (classMetaData.identityType == MDStatics.IDENTITY_TYPE_DATASTORE) {
0463:                        return new VersantOid(oid, modelMetaData, oid
0464:                                .isResolved());
0465:                    } else if (classMetaData.identityType == MDStatics.IDENTITY_TYPE_APPLICATION) {
0466:                        Object pcID = jdoImplHelper
0467:                                .newObjectIdInstance(classMetaData.cls);
0468:                        oid.populateObjectIdClassInstance(pcID);
0469:                        return pcID;
0470:                    } else {
0471:                        throw BindingSupportImpl.getInstance().unsupported();
0472:                    }
0473:                }
0474:            }
0475:
0476:            public Object getObjectByIDString(String value, boolean toValidate) {
0477:                return getObjectByIDString(value, toValidate, true);
0478:            }
0479:
0480:            public Object getObjectByIDString(String value, boolean toValidate,
0481:                    boolean resolved) {
0482:                try {
0483:                    OID oid = modelMetaData.newOIDFromIDString(value, resolved);
0484:                    return getObjectById(oid, toValidate);
0485:                } catch (Exception e) {
0486:                    handleException(e);
0487:                    return null;
0488:                }
0489:            }
0490:
0491:            public Object getTransactionalObjectId(Object pc) {
0492:                try {
0493:                    return getObjectId(pc);
0494:                } catch (Exception e) {
0495:                    handleException(e);
0496:                    return null;
0497:                }
0498:            }
0499:
0500:            //    public void batchDelete(Query q, Object[] params) {
0501:            //        VesantQueryImp clientQuery = (VesantQueryImp) q;
0502:            //        clientQuery.getQParamsForBatchProc(params);
0503:            //        throw new NotImplementedException();
0504:            //    }
0505:
0506:            public boolean isClosed() {
0507:                checkInPool();
0508:                if (!managed) {
0509:                    return closed;
0510:                } else {
0511:                    return managedClosed;
0512:                }
0513:            }
0514:
0515:            /**
0516:             * This is called by the user to close the pm. If in a managed environment the managedClosed
0517:             * flag will be set.
0518:             * <p/>
0519:             * If pooling is enabled the the instance must be reset to
0520:             * be put back in the pool.
0521:             * <p/>
0522:             * If pooling is not enabled then the instance must be reset to avoid mem leaks.
0523:             * The instance will never be used again.
0524:             * <p/>
0525:             * The current transaction will be rolled back if active.
0526:             * This means that synchronization events will be fired.
0527:             */
0528:            public synchronized void close() {
0529:                checkClosed();
0530:                if (!managed) {
0531:                    checkCloseWithActiveTx();
0532:                    boolean txWasActive = transactionActive;
0533:                    if (transactionActive) {
0534:                        rollback();
0535:                    }
0536:                    proxy.resetPM();
0537:                    pmf.pmClosedNotification(this , false, txWasActive);
0538:                } else {
0539:                    managedClosed = true;
0540:                }
0541:            }
0542:
0543:            private void checkCloseWithActiveTx() {
0544:                if (transactionActive && !pmf.isAllowPmCloseWithTxOpen()) {
0545:                    throw BindingSupportImpl
0546:                            .getInstance()
0547:                            .invalidOperation(
0548:
0549:                            "May not close 'PersistenceManager' with active transaction");
0550:
0551:                }
0552:            }
0553:
0554:            /**
0555:             * Destroy the PM. It cannot be reused after this call.
0556:             */
0557:            public void destroy() {
0558:                try {
0559:                    sm.reset();
0560:                    resetEpcFields();
0561:                    reset();
0562:                    cache.clear();
0563:                    this .closed = true;
0564:                } catch (Exception e) {
0565:                    handleException(e);
0566:                }
0567:            }
0568:
0569:            public boolean isActualClosed() {
0570:                return closed;
0571:            }
0572:
0573:            public Transaction currentTransaction() {
0574:                return this ;
0575:            }
0576:
0577:            public void refresh(Object pc) {
0578:                try {
0579:                    /**
0580:                     * if pc is transient / non-managed then return.
0581:                     */
0582:                    if (isTransient(pc))
0583:                        return;
0584:                    pmPreCheck(pc).refresh();
0585:                } catch (Exception e) {
0586:                    handleException(e);
0587:                }
0588:            }
0589:
0590:            public void setPmCacheRefType(Object pc, int type) {
0591:                pmPreCheck(pc).cacheEntry.changeToRefType(cache.queue, type);
0592:            }
0593:
0594:            public void setPmCacheRefType(Object[] pcs, int type) {
0595:                for (int i = 0; i < pcs.length; i++) {
0596:                    if (pcs[i] != null)
0597:                        setPmCacheRefType(pcs[i], type);
0598:                }
0599:            }
0600:
0601:            public void setPmCacheRefType(Collection col, int type) {
0602:                for (Iterator iterator = col.iterator(); iterator.hasNext();) {
0603:                    Object o = iterator.next();
0604:                    if (o != null)
0605:                        setPmCacheRefType(o, type);
0606:                }
0607:            }
0608:
0609:            public void setPmCacheRefType(int type) {
0610:                cache.setCurrentRefType(type);
0611:            }
0612:
0613:            public int getPmCacheRefType() {
0614:                return cache.getCurrentRefType();
0615:            }
0616:
0617:            public void refreshAll(Object[] pcs) {
0618:                try {
0619:                    for (int i = 0; i < pcs.length; i++) {
0620:                        refresh(pcs[i]);
0621:                    }
0622:                } catch (Exception e) {
0623:                    handleException(e);
0624:                }
0625:            }
0626:
0627:            public void refreshAll(Collection pcs) {
0628:                if (pcs instanceof  QueryResult) {
0629:                    cache.setOverWriteMode(true);
0630:                    try {
0631:                        Iterator iter = ((QueryResult) pcs)
0632:                                .createInternalIterNoFlush();
0633:                        while (iter.hasNext())
0634:                            iter.next();
0635:                    } catch (Exception e) {
0636:                        handleException(e);
0637:                    } finally {
0638:                        cache.setOverWriteMode(false);
0639:                    }
0640:                } else {
0641:                    try {
0642:                        for (Iterator iterator = pcs.iterator(); iterator
0643:                                .hasNext();) {
0644:                            refresh(iterator.next());
0645:                        }
0646:                    } catch (Exception e) {
0647:                        handleException(e);
0648:                    }
0649:                }
0650:            }
0651:
0652:            public void refreshAll() {
0653:                try {
0654:                    if (transactionActive) {
0655:                        cache.doRefresh(strict);
0656:                    }
0657:                } catch (Exception e) {
0658:                    handleException(e);
0659:                }
0660:            }
0661:
0662:            public Query newQuery() {
0663:                try {
0664:                    return new VersantQueryImp(proxy);
0665:                } catch (Exception e) {
0666:                    handleException(e);
0667:                    return null;
0668:                }
0669:            }
0670:
0671:            public Query newQuery(Object compiled) {
0672:                //        if (compiled instanceof JavaQuery) {
0673:                //            return newQuery((JavaQuery) compiled);
0674:                //        }
0675:                try {
0676:                    VersantQueryImp other = null;
0677:                    try {
0678:                        other = (VersantQueryImp) compiled;
0679:                    } catch (Exception e) {
0680:                        throw BindingSupportImpl
0681:                                .getInstance()
0682:                                .invalidOperation(
0683:                                        "The supplied instance is not supported to re-create a query from.");
0684:                    }
0685:                    return new VersantQueryImp(proxy, other);
0686:                } catch (RuntimeException e) {
0687:                    handleException(e);
0688:                    return null;
0689:                }
0690:            }
0691:
0692:            //    public Query newQuery(JavaQuery javaQuery) {
0693:            //            try {
0694:            //                JavaQueryParams query = null;
0695:            //                try {
0696:            //                    query = (JavaQueryParams) javaQuery;
0697:            //                } catch (ClassCastException e) {
0698:            //                    throw BindingSupportImpl.getInstance().invalidOperation(
0699:            //                            "JavaQuery has not been enhanced.");
0700:            //                }
0701:            //                VesantQueryImp clientQuery = new VesantQueryImp(proxy);
0702:            //                clientQuery.setClass(query.getQueryClass());
0703:            //                clientQuery.setFilter(query.getFilter());
0704:            //                clientQuery.setOrdering(query.getOrdering());
0705:            //                clientQuery.declareParameters(query.getParameters());
0706:            //                clientQuery.declareVariables(query.getVariables());
0707:            //                return clientQuery;
0708:            //            } catch (Exception e) {
0709:            //                handleException(e);
0710:            //                return null;
0711:            //            }
0712:            //    }
0713:            //
0714:            //    public Query newNamedQuery(Class cls, String queryName) {
0715:            //        return null;
0716:            //    }
0717:
0718:            public Query newQuery(String language, Object query) {
0719:                try {
0720:                    if (language != null) {
0721:                        language = language.toUpperCase();
0722:                    }
0723:                    if (LANGUAGE_SQL.equals(language)) {
0724:                        VersantQueryImp clientQuery = new VersantQueryImp(
0725:                                proxy, QueryDetails.LANGUAGE_SQL);
0726:                        clientQuery.setFilter((String) query);
0727:                        return clientQuery;
0728:
0729:                    } else if (LANGUAGE_EJBQL.equals(language)) {
0730:                        VersantQueryImp clientQuery = new VersantQueryImp(
0731:                                proxy, QueryDetails.LANGUAGE_EJBQL);
0732:                        clientQuery.setFilter((String) query);
0733:                        return clientQuery;
0734:                    } else {
0735:                        return newQuery(query);
0736:                    }
0737:                } catch (Exception e) {
0738:                    handleException(e);
0739:                    return null;
0740:                }
0741:            }
0742:
0743:            public Query newQuery(Class cls) {
0744:                try {
0745:                    VersantQueryImp clientQuery = new VersantQueryImp(proxy);
0746:                    clientQuery.setClass(cls);
0747:                    return clientQuery;
0748:                } catch (Exception e) {
0749:                    handleException(e);
0750:                    return null;
0751:                }
0752:            }
0753:
0754:            public Query newQuery(Extent extent) {
0755:                try {
0756:                    VersantQueryImp clientQuery = new VersantQueryImp(proxy);
0757:                    clientQuery.setCandidates(extent);
0758:                    return clientQuery;
0759:                } catch (Exception e) {
0760:                    handleException(e);
0761:                    return null;
0762:                }
0763:            }
0764:
0765:            public Query newQuery(Extent extent, String filter) {
0766:                try {
0767:                    VersantQueryImp clientQuery = new VersantQueryImp(proxy);
0768:                    clientQuery.setCandidates(extent);
0769:                    clientQuery.setFilter(filter);
0770:                    return clientQuery;
0771:                } catch (Exception e) {
0772:                    handleException(e);
0773:                    return null;
0774:                }
0775:            }
0776:
0777:            public Query newQuery(Class cls, Collection cln) {
0778:                try {
0779:                    VersantQueryImp clientQuery = new VersantQueryImp(proxy);
0780:                    clientQuery.setClass(cls);
0781:                    clientQuery.setCandidates(cln);
0782:                    return clientQuery;
0783:                } catch (Exception e) {
0784:                    handleException(e);
0785:                    return null;
0786:                }
0787:            }
0788:
0789:            public Query newQuery(Class cls, String filter) {
0790:                try {
0791:                    VersantQueryImp clientQuery = new VersantQueryImp(proxy);
0792:                    clientQuery.setClass(cls);
0793:                    clientQuery.setFilter(filter);
0794:                    return clientQuery;
0795:                } catch (Exception e) {
0796:                    handleException(e);
0797:                    return null;
0798:                }
0799:            }
0800:
0801:            public Query newQuery(Class cls, Collection cln, String filter) {
0802:                try {
0803:                    VersantQueryImp clientQuery = new VersantQueryImp(proxy);
0804:                    clientQuery.setClass(cls);
0805:                    clientQuery.setCandidates(cln);
0806:                    clientQuery.setFilter(filter);
0807:                    return clientQuery;
0808:                } catch (Exception e) {
0809:                    handleException(e);
0810:                    return null;
0811:                }
0812:            }
0813:
0814:            public Class getObjectIdClass(Class cls) {
0815:                try {
0816:                    if (cls == null) {
0817:                        return null;
0818:                        //            throw new JDOUserException("The supplied Class param is null");
0819:                    }
0820:                    if (!PersistenceCapable.class.isAssignableFrom(cls)) {
0821:                        return null;
0822:                    }
0823:                    if (Modifier.isAbstract(cls.getModifiers())) {
0824:                        return null;
0825:                    }
0826:                    ClassMetaData cmd = modelMetaData.getClassMetaData(cls);
0827:                    if (cmd == null) {
0828:                        throw BindingSupportImpl.getInstance()
0829:                                .invalidOperation(
0830:                                        "The class is not specified as "
0831:                                                + PersistenceCapable.class
0832:                                                        .getName()
0833:                                                + " for the application");
0834:                    }
0835:                    if (cmd.identityType == MDStatics.IDENTITY_TYPE_APPLICATION) {
0836:                        return cmd.objectIdClass;
0837:                    } else {
0838:                        return VersantOid.class;
0839:                    }
0840:                } catch (RuntimeException e) {
0841:                    handleException(e);
0842:                    return null;
0843:                }
0844:            }
0845:
0846:            public Object newObjectIdInstance(Class cls, String s) {
0847:                return newObjectIdInstance(cls, s, true);
0848:            }
0849:
0850:            public Object newObjectIdInstance(Class cls, String s,
0851:                    boolean resolved) {
0852:                try {
0853:                    if (s == null || s.length() == 0) {
0854:                        throw BindingSupportImpl
0855:                                .getInstance()
0856:                                .invalidOperation(
0857:                                        "Please supply an non-null, non-empty String");
0858:                    }
0859:                    if (cls == null) { // assume datastore identity
0860:                        return new VersantOid(modelMetaData.newOIDFromIDString(
0861:                                s, resolved), modelMetaData, resolved);
0862:                    }
0863:                    ClassMetaData cmd = modelMetaData.getClassMetaData(cls);
0864:                    if (cmd == null) {
0865:                        throw BindingSupportImpl.getInstance()
0866:                                .invalidOperation(
0867:                                        "There is no metadata registered for class '"
0868:                                                + cls.getName() + "'");
0869:                    }
0870:                    if (cmd.identityType == MDStatics.IDENTITY_TYPE_APPLICATION) {
0871:                        return jdoImplHelper.newObjectIdInstance(cls, s);
0872:                    } else if (cmd.identityType == MDStatics.IDENTITY_TYPE_DATASTORE) {
0873:                        return new VersantOid(modelMetaData.newOIDFromIDString(
0874:                                s, resolved), modelMetaData, resolved);
0875:                    } else {
0876:                        throw BindingSupportImpl.getInstance()
0877:                                .invalidOperation(
0878:                                        "Class '" + cls.getName()
0879:                                                + " uses non-durable identity");
0880:                    }
0881:                } catch (RuntimeException e) {
0882:                    handleException(e);
0883:                    return null;
0884:                }
0885:            }
0886:
0887:            public void retrieve(Object o) {
0888:                try {
0889:                    PCStateMan pcStateObject = pmPreCheck(o);
0890:                    if (pcStateObject != null) {
0891:                        try {
0892:                            if (Debug.DEBUG) {
0893:                                if (retrieveing) {
0894:                                    throw BindingSupportImpl
0895:                                            .getInstance()
0896:                                            .internal(
0897:                                                    "Retrieveing is already set");
0898:                                }
0899:                            }
0900:                            retrieveing = true;
0901:                            if (Debug.DEBUG) {
0902:                                if (retrieveSet.contains(pcStateObject.pc)) {
0903:                                    throw BindingSupportImpl
0904:                                            .getInstance()
0905:                                            .internal(
0906:                                                    "RetrieveSet already contains pc");
0907:                                }
0908:                            }
0909:                            retrieveSet.add(pcStateObject.pc);
0910:                            pcStateObject.retrieve(this );
0911:                        } finally {
0912:                            retrieveing = false;
0913:                            retrieveSet.clear();
0914:                        }
0915:                    }
0916:                } catch (RuntimeException e) {
0917:                    if (BindingSupportImpl.getInstance()
0918:                            .isOwnInternalException(e)) {
0919:                        handleException(e);
0920:                    } else {
0921:                        throw e;
0922:                    }
0923:                }
0924:            }
0925:
0926:            public void retrieveImp(Object o) {
0927:                if (o == null)
0928:                    return;
0929:                PCStateMan pcStateObject = pmPreCheck(o);
0930:                if (pcStateObject != null
0931:                        && !retrieveSet.contains(pcStateObject.pc)) {
0932:                    retrieveSet.add(pcStateObject.pc);
0933:                    pcStateObject.retrieve(this );
0934:                }
0935:            }
0936:
0937:            public void retrieveAllImp(Object[] toRetrieve) {
0938:                for (int i = 0; i < toRetrieve.length; i++) {
0939:                    retrieveImp(toRetrieve[i]);
0940:                }
0941:            }
0942:
0943:            public void retrieveAllImp(Collection toRetrieve) {
0944:                retrieveAllImp(toRetrieve.toArray());
0945:            }
0946:
0947:            public void retrieveAll(Collection collection) {
0948:                try {
0949:                    retrieveAll(collection.toArray());
0950:                } catch (Exception e) {
0951:                    handleException(e);
0952:                }
0953:            }
0954:
0955:            public void retrieveAll(Collection collection, boolean b) {
0956:                retrieveAll(collection);
0957:            }
0958:
0959:            public void retrieveAll(Object[] objects, boolean b) {
0960:                retrieveAll(objects);
0961:            }
0962:
0963:            public void retrieveAll(Object[] objects) {
0964:                try {
0965:                    try {
0966:                        if (Debug.DEBUG) {
0967:                            if (retrieveing) {
0968:                                throw BindingSupportImpl.getInstance()
0969:                                        .internal("Retrieveing is already set");
0970:                            }
0971:                        }
0972:                        retrieveing = true;
0973:                        for (int i = 0; i < objects.length; i++) {
0974:                            retrieveImp(objects[i]);
0975:                        }
0976:                    } finally {
0977:                        retrieveing = false;
0978:                        retrieveSet.clear();
0979:                    }
0980:                } catch (RuntimeException e) {
0981:                    if (BindingSupportImpl.getInstance()
0982:                            .isOwnInternalException(e)) {
0983:                        handleException(e);
0984:                    } else {
0985:                        throw e;
0986:                    }
0987:                }
0988:            }
0989:
0990:            /**
0991:             * todo keep extent's around instead of creating a new one.
0992:             *
0993:             * @param persistenceCapableClass
0994:             * @param subclasses
0995:             * @return
0996:             */
0997:            public Extent getExtent(Class persistenceCapableClass,
0998:                    boolean subclasses) {
0999:                try {
1000:                    return new ExtentImp(persistenceCapableClass, subclasses,
1001:                            proxy);
1002:                } catch (Exception e) {
1003:                    handleException(e);
1004:                    return null;
1005:                }
1006:            }
1007:
1008:            /**
1009:             * Util method to return the fetchgroup index.
1010:             */
1011:            private int getFgIndex(OID nOID, String fetchGroupName) {
1012:                int fgIndex = 0;
1013:                FetchGroup fg = nOID.getAvailableClassMetaData().getFetchGroup(
1014:                        fetchGroupName);
1015:                if (fg != null) {
1016:                    fgIndex = fg.index;
1017:                }
1018:                return fgIndex;
1019:            }
1020:
1021:            public Object getObjectById(Object oid, boolean validate) {
1022:                if (oid == null) {
1023:                    throw BindingSupportImpl.getInstance().invalidOperation(
1024:                            "The supplied oid is null");
1025:                }
1026:
1027:                PersistenceCapable pc = null;
1028:                try {
1029:                    OID nOID = extractOID(oid);
1030:                    PCStateMan stateMan = cache.getByOID(nOID, true);
1031:                    if (stateMan == null) {
1032:                        if (!nOID.isNew()) {
1033:                            /**
1034:                             * A call to getObjectById(id, false) with a where
1035:                             * (idType == appId) and (oid.cmd.usekeygen == true)
1036:                             * will always be validated against the db. This is done
1037:                             * because an inconsistent mapping
1038:                             * may arise.
1039:                             *
1040:                             * Scenario: A new instance of this type is created and made
1041:                             * persistent. This instance is now in the
1042:                             * managed cache with a internal tmp oid.
1043:                             * A call to getObjectById(id, false) is made with a id
1044:                             * value of 2 for example. This instance will also
1045:                             * end up in the managed cache with a real app id with value 2.
1046:                             * On a call to commit the keygen will allocate a value to
1047:                             * the new id instance. If this value is also
1048:                             * assigned the value '2' then there will both instances
1049:                             * wants the same id but the are already assigned
1050:                             * different pc instance values.
1051:                             *
1052:                             * Also added check for an unresolved oid that is in a hierarchy.
1053:                             * Such oids are also always resolved.
1054:                             * This could be changed later to keep such an instance in an
1055:                             * initialised state.
1056:                             */
1057:                            if (validate
1058:                                    || (nOID.getAvailableClassMetaData().useKeyGen && nOID
1059:                                            .getAvailableClassMetaData().identityType == MDStatics.IDENTITY_TYPE_APPLICATION)
1060:                                    || (!nOID.isResolved() && nOID
1061:                                            .getAvailableClassMetaData()
1062:                                            .isInHeirachy())) {
1063:                                checkNonTxRead();
1064:                                OID nOIDcopy = nOID.copy();
1065:                                stateMan = getStateMan(nOIDcopy, 0, -1, -1,
1066:                                        validate);
1067:
1068:                                if (stateMan == null) {
1069:                                    throw BindingSupportImpl
1070:                                            .getInstance()
1071:                                            .objectNotFound(
1072:                                                    "No row for "
1073:                                                            + nOID
1074:                                                                    .getAvailableClassMetaData().storeClass
1075:                                                            + " "
1076:                                                            + nOID.toSString());
1077:                                }
1078:
1079:                                pc = stateMan.pc;
1080:                                stateMan.loadDFGIntoPC(this );
1081:                            } else {
1082:                                //create the sm
1083:                                PCStateMan sm = getStateObject();
1084:                                sm.init(nOID, this );
1085:                                pc = sm.pc;
1086:                                cache.add(sm);
1087:                            }
1088:                        } else {
1089:                            throw BindingSupportImpl.getInstance()
1090:                                    .objectNotFound(
1091:                                            "No row for " + nOID.toSString());
1092:                        }
1093:                    } else {
1094:                        pc = stateMan.pc;
1095:                        if (validate && !stateMan.isTransactional(null)) {
1096:                            checkNonTxRead();
1097:                            if (stateMan.isHollow()) {
1098:                                stateMan.loadDfgFromHollow();
1099:                            } else {
1100:                                getState(stateMan.oid, null, 0, -1, -1, true);
1101:                            }
1102:                        }
1103:                    }
1104:                    return pc;
1105:                } catch (Exception e) {
1106:                    handleException(e);
1107:                    return null;
1108:                }
1109:            }
1110:
1111:            public OID extractOID(Object oid) {
1112:                OID nOID;
1113:                if (oid instanceof  VersantOid) {
1114:                    nOID = modelMetaData
1115:                            .convertJDOGenieOIDtoOID((VersantOid) oid);
1116:                    nOID = convertNewToActual(nOID);
1117:                } else if (oid instanceof  OID) {
1118:                    nOID = convertNewToActual((OID) oid);
1119:                } else {
1120:                    nOID = modelMetaData.convertFromAppIdToOID(oid);
1121:                }
1122:                return nOID;
1123:            }
1124:
1125:            /**
1126:             * This is use by State implementations when they need to retrieve an
1127:             * instance. This will typically be a result of graph navigation.
1128:             * The oid parameter is not used when an embedded reference field is
1129:             * being retrieved.
1130:             */
1131:            public Object getObjectByIdForState(OID oid, int stateFieldNo,
1132:                    int navClassIndex, OID fromOID) {
1133:                try {
1134:                    PersistenceCapable pc;
1135:                    FieldMetaData fmd = fromOID.getAvailableClassMetaData().stateFields[stateFieldNo];
1136:                    if (fmd.embedded) {
1137:                        //create a managed instance of the embedded reference
1138:                        PCStateMan owningSM = cache.getByOID(fromOID, false);
1139:                        if (fmd.nullIndicatorFmd != null) {
1140:                            if (owningSM.state
1141:                                    .isFieldNullorZero(fmd.nullIndicatorFmd.stateFieldNo)) {
1142:                                return null;
1143:                            }
1144:                        }
1145:                        EmbeddedStateManager embeddedSm = owningSM
1146:                                .createEmbeddedSM(fmd);
1147:                        pc = embeddedSm.pc;
1148:                    } else {
1149:                        PCStateMan stateMan = cache.getByOID(oid, true);
1150:                        if (stateMan == null) {
1151:                            stateMan = getStateMan(oid, 0, stateFieldNo,
1152:                                    navClassIndex, false);
1153:                            if (stateMan != null) {
1154:                                pc = stateMan.pc;
1155:                                stateMan.loadDFGIntoPC(this );
1156:                            } else {
1157:                                pc = null;
1158:                            }
1159:                        } else {
1160:                            pc = stateMan.pc;
1161:                            if (!stateMan.isTransactional(null)) {
1162:                                checkNonTxRead();
1163:                                //TODO why loadDfg. Is it not better to leave the state hollow
1164:                                if (stateMan.isHollow())
1165:                                    stateMan.loadDfgFromHollow();
1166:                            }
1167:                        }
1168:                    }
1169:                    return pc;
1170:                } catch (Exception e) {
1171:                    handleException(e);
1172:                    return null;
1173:                }
1174:            }
1175:
1176:            public final void checkNonTxRead() {
1177:                if (!(transactionActive || nontransactionalRead)) {
1178:                    throw BindingSupportImpl.getInstance().invalidOperation(
1179:                            "Must set nonTransactionalRead to true");
1180:                }
1181:            }
1182:
1183:            public final void checkNonTxWrite() {
1184:                if (!(transactionActive || nontransactionalWrite)) {
1185:                    throw BindingSupportImpl.getInstance().invalidOperation(
1186:                            "Must set nonTransactionalWrite to true");
1187:                }
1188:            }
1189:
1190:            public boolean doBeforeState(boolean isTransient,
1191:                    boolean isTransactional) {
1192:                return ((restoreValues || isTransient || isTransactional) && transactionActive);
1193:            }
1194:
1195:            private OID convertNewToActual(OID oid) {
1196:                if (!oid.isNew()) {
1197:                    oid.getAvailableClassMetaData();
1198:                    return oid;
1199:                }
1200:                return oid.getAvailableOID();
1201:            }
1202:
1203:            public void makePersistent(final Object o) {
1204:                try {
1205:                    if (o == null) {
1206:                        throw BindingSupportImpl
1207:                                .getInstance()
1208:                                .invalidOperation(
1209:                                        "makePersistent called with null object");
1210:                    }
1211:                    checkActiveTx();
1212:                    PCStateMan root = txDirtyListHead;
1213:                    makeReachablePersistent(o);
1214:                    if (root == null) {
1215:                        root = txDirtyListTail;
1216:                    } else {
1217:                        root = root.next;
1218:                    }
1219:
1220:                    for (; root != null; root = root.next)
1221:                        root.addRefs();
1222:                } catch (Exception e) {
1223:                    handleException(e);
1224:                }
1225:            }
1226:
1227:            /**
1228:             * Make an instance found in a reachability search persistent. This skips
1229:             * some checks done by makePersistent for speed. Note that this does not
1230:             * add reachable instances.<p>
1231:             */
1232:            public void makeReachablePersistent(final Object o) {
1233:                if (o == null)
1234:                    return;
1235:                PersistenceCapable pc = checkPersCapable(o);
1236:                PersistenceManager pm = pc.jdoGetPersistenceManager();
1237:                if (pm == null) {
1238:                    reManage(pc, assignOID(pc), false);
1239:                } else {
1240:                    PMProxy pmProxy = (PMProxy) pm;
1241:                    if (pmProxy.getRealPM() != this ) {
1242:                        throw BindingSupportImpl.getInstance()
1243:                                .invalidOperation(
1244:                                        "Object is managed by " + pm
1245:                                                + " (this is " + proxy + "): "
1246:                                                + pc.getClass() + ": "
1247:                                                + Utils.toString(pc));
1248:                    }
1249:                }
1250:            }
1251:
1252:            public void makePersistentAll(final Object[] pcs) {
1253:                try {
1254:                    ArrayList failed = null;
1255:                    for (int i = 0; i < pcs.length; i++) {
1256:                        Object pc = pcs[i];
1257:                        try {
1258:                            makePersistent(pc);
1259:                        } catch (RuntimeException e) {
1260:                            if (BindingSupportImpl.getInstance()
1261:                                    .isOwnException(e)) {
1262:                                if (BindingSupportImpl.getInstance()
1263:                                        .getFailedObject(e) == null) {
1264:                                    e = BindingSupportImpl.getInstance()
1265:                                            .exception(e.getMessage(), e, pc);
1266:                                }
1267:                                if (failed == null)
1268:                                    failed = new ArrayList();
1269:                                failed.add(e);
1270:                            } else {
1271:                                throw e;
1272:                            }
1273:                        }
1274:                    }
1275:                    if (failed != null) {
1276:                        int n = failed.size();
1277:                        if (n == 1) {
1278:                            throw (Exception) failed.get(0);
1279:                        } else {
1280:                            Throwable[] a = new Throwable[n];
1281:                            failed.toArray(a);
1282:                            throw BindingSupportImpl.getInstance().exception(
1283:                                    n + " instances failed to persist", a);
1284:                        }
1285:                    }
1286:                } catch (Exception e) {
1287:                    handleException(e);
1288:                }
1289:            }
1290:
1291:            public void makePersistentAll(final Collection pcs) {
1292:                try {
1293:                    ArrayList failed = null;
1294:                    for (Iterator i = pcs.iterator(); i.hasNext();) {
1295:                        Object pc = i.next();
1296:                        try {
1297:                            makePersistent(pc);
1298:                        } catch (RuntimeException e) {
1299:                            if (BindingSupportImpl.getInstance()
1300:                                    .isOwnException(e)) {
1301:                                if (BindingSupportImpl.getInstance()
1302:                                        .getFailedObject(e) == null) {
1303:                                    e = BindingSupportImpl.getInstance()
1304:                                            .exception(e.getMessage(), e, pc);
1305:                                }
1306:                                if (failed == null)
1307:                                    failed = new ArrayList();
1308:                                failed.add(e);
1309:                            } else {
1310:                                throw e;
1311:                            }
1312:                        }
1313:                    }
1314:                    if (failed != null) {
1315:                        int n = failed.size();
1316:                        if (n == 1) {
1317:                            throw (Exception) failed.get(0);
1318:                        } else {
1319:                            Throwable[] a = new Throwable[n];
1320:                            failed.toArray(a);
1321:                            throw BindingSupportImpl.getInstance().exception(
1322:                                    n + " instances failed to persist", a);
1323:                        }
1324:                    }
1325:                } catch (Exception e) {
1326:                    handleException(e);
1327:                }
1328:            }
1329:
1330:            /**
1331:             * @param pcs
1332:             */
1333:            public void deletePersistentAll(Object[] pcs) {
1334:                try {
1335:                    for (int i = 0; i < pcs.length; i++) {
1336:                        deletePersistent(pcs[i]);
1337:                    }
1338:                } catch (Exception e) {
1339:                    handleException(e);
1340:                }
1341:            }
1342:
1343:            /**
1344:             * @param pc
1345:             */
1346:            public void deletePersistent(Object pc) {
1347:                checkActiveTx();
1348:                if (isTransient(pc)) {
1349:                    throw BindingSupportImpl.getInstance().invalidOperation(
1350:                            "The instance is transient");
1351:                }
1352:                try {
1353:                    pmPreCheck(pc).deletePersistent();
1354:                } catch (Exception e) {
1355:                    handleException(e);
1356:                }
1357:            }
1358:
1359:            /**
1360:             * @param pcs
1361:             */
1362:            public void deletePersistentAll(Collection pcs) {
1363:                try {
1364:                    for (Iterator iterator = pcs.iterator(); iterator.hasNext();) {
1365:                        deletePersistent(iterator.next());
1366:                    }
1367:                } catch (Exception e) {
1368:                    handleException(e);
1369:                }
1370:            }
1371:
1372:            /**
1373:             * TODO: Remove the instance from the weak caches.
1374:             *
1375:             * @param pc
1376:             */
1377:            public void makeTransient(Object pc) {
1378:                checkPersCapable(pc);
1379:                try {
1380:                    if (isTransient(pc)) {
1381:                        //the instance is already transient.
1382:                        return;
1383:                    }
1384:                    pmPreCheck(pc).makeTransient();
1385:                } catch (Exception e) {
1386:                    handleException(e);
1387:                }
1388:            }
1389:
1390:            public void makeTransientRecursive(Object pc) {
1391:                checkPersCapable(pc);
1392:                try {
1393:                    if (isTransient(pc)) {
1394:                        //the instance is already transient.
1395:                        return;
1396:                    }
1397:                    pmPreCheck(pc).makeTransientRecursive();
1398:                } catch (Exception e) {
1399:                    handleException(e);
1400:                }
1401:            }
1402:
1403:            /**
1404:             * TODO: Remove the instance from the weak caches.
1405:             *
1406:             * @param pcs
1407:             */
1408:            public void makeTransientAll(Object[] pcs) {
1409:                try {
1410:                    Map failed = new HashMap();
1411:                    for (int i = 0; i < pcs.length; i++) {
1412:                        Object pc = pcs[i];
1413:                        try {
1414:                            makeTransient(pc);
1415:                        } catch (Exception e) {
1416:                            failed.put(pc, e);
1417:                        }
1418:                    }
1419:                    if (failed.size() > 0) {
1420:                        throw BindingSupportImpl.getInstance()
1421:                                .invalidOperation(
1422:                                        "Errors occured with makeTransientAll: "
1423:                                                + failed);
1424:                    }
1425:                } catch (RuntimeException e) {
1426:                    handleException(e);
1427:                }
1428:            }
1429:
1430:            /**
1431:             * TODO: Remove the instance from the weak caches.
1432:             *
1433:             * @param pcs
1434:             */
1435:            public void makeTransientAll(Collection pcs) {
1436:                try {
1437:                    if (pcs == null)
1438:                        return;
1439:                    makeTransientAll(pcs.toArray());
1440:                } catch (Exception e) {
1441:                    handleException(e);
1442:                }
1443:            }
1444:
1445:            private final boolean isTransient(Object pc) {
1446:                if (JDOHelper.getPersistenceManager(pc) == null) {
1447:                    return true;
1448:                }
1449:                return false;
1450:            }
1451:
1452:            public void makeTransactional(Object pc) {
1453:                try {
1454:                    if (JDOHelper.getPersistenceManager(pc) == null) {
1455:                        //this is a transient instance
1456:                        reManage((PersistenceCapable) pc,
1457:                                assignOID((PersistenceCapable) pc), true);
1458:                    }
1459:                    PCStateMan pcStateObject = pmPreCheck(pc);
1460:                    pcStateObject.makeTransactional();
1461:                } catch (Exception e) {
1462:                    handleException(e);
1463:                }
1464:            }
1465:
1466:            public void makeTransactionalAll(Object[] pcs) {
1467:                if (pcs == null)
1468:                    return;
1469:                try {
1470:                    Map failed = new HashMap(pcs.length);
1471:                    for (int i = 0; i < pcs.length; i++) {
1472:                        Object pc = pcs[i];
1473:                        try {
1474:                            makeTransactional(pc);
1475:                        } catch (Exception e) {
1476:                            failed.put(pc, e);
1477:                        }
1478:                    }
1479:                    if (failed.size() > 0) {
1480:                        throw BindingSupportImpl.getInstance()
1481:                                .invalidOperation(
1482:                                        "Errors occured with makePersistentAll:"
1483:                                                + failed);
1484:                    }
1485:                } catch (RuntimeException e) {
1486:                    handleException(e);
1487:                }
1488:            }
1489:
1490:            public void makeTransactionalAll(Collection pcs) {
1491:                if (pcs == null)
1492:                    return;
1493:                try {
1494:                    makeTransactionalAll(pcs.toArray());
1495:                } catch (Exception e) {
1496:                    handleException(e);
1497:                }
1498:            }
1499:
1500:            private final void makeNonTransactionalImp(Object pc) {
1501:                PCStateMan pcStateObject = pmPreCheck(pc);
1502:                pcStateObject.makeNonTransactional();
1503:            }
1504:
1505:            public void makeNontransactional(Object pc) {
1506:                try {
1507:                    makeNonTransactionalImp(pc);
1508:                } catch (Exception e) {
1509:                    handleException(e);
1510:                }
1511:            }
1512:
1513:            public void makeNontransactionalAll(Object[] pcs) {
1514:                try {
1515:                    for (int i = 0; i < pcs.length; i++) {
1516:                        makeNonTransactionalImp(pcs[i]);
1517:                    }
1518:                } catch (Exception e) {
1519:                    handleException(e);
1520:                }
1521:            }
1522:
1523:            public void makeNontransactionalAll(Collection pcs) {
1524:                for (Iterator iterator = pcs.iterator(); iterator.hasNext();) {
1525:                    makeNonTransactionalImp(iterator.next());
1526:                }
1527:            }
1528:
1529:            public void setUserObject(Object o) {
1530:                try {
1531:                    sm.setUserObject(userObject = o);
1532:                } catch (Exception e) {
1533:                    handleException(e);
1534:                }
1535:            }
1536:
1537:            public Object getUserObject() {
1538:                return userObject;
1539:            }
1540:
1541:            public PersistenceManagerFactory getPersistenceManagerFactory() {
1542:                return pmf;
1543:            }
1544:
1545:            public void setMultithreaded(boolean flag) {
1546:                // Changing from multithreaded false to true is not allowed. This must
1547:                // be done at the PMF level before the PM is created.
1548:                if (flag && !multithreaded) {
1549:                    throw BindingSupportImpl
1550:                            .getInstance()
1551:                            .invalidOperation(
1552:                                    "PM.setMultithreaded(true) is not allowed if the PM "
1553:                                            + "was created from a PMF with multithreaded false");
1554:                }
1555:                // ignore the true -> false transition as the extra synchronization
1556:                // has only a performance impact
1557:            }
1558:
1559:            public boolean getMultithreaded() {
1560:                return multithreaded;
1561:            }
1562:
1563:            public void setMultithreadedImp(boolean flag) {
1564:                multithreaded = flag;
1565:                createProxy();
1566:            }
1567:
1568:            public void setIgnoreCache(boolean flag) {
1569:                this .ignoreCache = flag;
1570:            }
1571:
1572:            public boolean getIgnoreCache() {
1573:                return this .ignoreCache;
1574:            }
1575:
1576:            /**
1577:             * Does a preCheck on a object claimed to be PersistanceCapable and managed by
1578:             * this pm.
1579:             */
1580:            private final PCStateMan pmPreCheck(final Object pc) {
1581:                return pmPreCheck(checkPersCapable(pc));
1582:
1583:            }
1584:
1585:            private PCStateMan pmPreCheck(PersistenceCapable pc) {
1586:                if (!checkManagedBy(pc)) {
1587:                    return null;
1588:                }
1589:                PCStateMan pcState = getInternalSM(pc);
1590:                if (Debug.DEBUG) {
1591:                    if (pcState == null
1592:                            && JDOHelper.getPersistenceManager(pc) != null) {
1593:                        throw BindingSupportImpl
1594:                                .getInstance()
1595:                                .internal(
1596:                                        "The pm is set on instance but is not in weak list");
1597:                    }
1598:                }
1599:                return pcState;
1600:            }
1601:
1602:            private final boolean checkManagedBy(PersistenceCapable pc) {
1603:                PMProxy pm = (PMProxy) pc.jdoGetPersistenceManager();
1604:                if (pm != null) {
1605:                    if (pm == proxy)
1606:                        return true;
1607:                    throw BindingSupportImpl.getInstance().invalidOperation(
1608:                            "Object is managed by " + pm + " (this is " + proxy
1609:                                    + "): " + pc.getClass() + ": "
1610:                                    + Utils.toString(pc));
1611:                }
1612:                return false;
1613:            }
1614:
1615:            private final void checkActiveTx() {
1616:                if (!isActive()) {
1617:                    throw BindingSupportImpl.getInstance().invalidOperation(
1618:                            "No active transaction.");
1619:                }
1620:            }
1621:
1622:            public void begin() {
1623:                if (managed) {
1624:                    throw BindingSupportImpl
1625:                            .getInstance()
1626:                            .invalidOperation(
1627:                                    "May not call begin in managed transaction environment");
1628:                }
1629:                beginImp();
1630:            }
1631:
1632:            private void beginImp() {
1633:                if (transactionActive) {
1634:                    throw BindingSupportImpl.getInstance().invalidOperation(
1635:                            "The transaction is already active");
1636:                }
1637:                try {
1638:                    transactionActive = true;
1639:                    sm.begin(optimistic);
1640:                    if (!optimistic && !interceptDfgFieldAccess) {
1641:                        cache.setInterceptDfgFieldAccess(true);
1642:                    }
1643:                } catch (Exception e) {
1644:                    handleException(e);
1645:                }
1646:            }
1647:
1648:            /**
1649:             * This is for client to rollback the connection. This will try to
1650:             * orderly rollback the data. The pm will be reset if an internal exception
1651:             * happens during rollback. The pm must be reset as new to avoid inconsistent behaviour.
1652:             * <p/>
1653:             * NB
1654:             * TODO ensure that all tx instances are rolledback properly.
1655:             * If for instance the are already removed out of the tx list at commit
1656:             * time then they can not undergo a rollback.
1657:             */
1658:            public void rollback() {
1659:                if (Debug.DEBUG) {
1660:                    System.out
1661:                            .println(">>>>>>>>>>> JdoGeniePersistenceManagerImp.rollback <<<<<<<<<<<<<<<");
1662:                }
1663:                if (managed) {
1664:                    throw BindingSupportImpl
1665:                            .getInstance()
1666:                            .invalidOperation(
1667:                                    "May not call rollback in managed transaction environment");
1668:                }
1669:                rollbackImp();
1670:            }
1671:
1672:            /**
1673:             * Reset this PM after an internal error of some kind. This just flags
1674:             * it to not go back in the pool.
1675:             */
1676:            private void fatalReset() {
1677:                mustNotPool = true;
1678:            }
1679:
1680:            /**
1681:             * This is called by JDOConnectionImpProxy when it handles a
1682:             * JDOFatalException from a call to the JDOConnection.
1683:             */
1684:            public void rollbackForFatalExceptionInJDOConnectionProxy() {
1685:                if (managed || !transactionActive)
1686:                    return;
1687:                rollbackImp();
1688:            }
1689:
1690:            /**
1691:             * This is an orderly rollback.
1692:             */
1693:            private void rollbackImp() {
1694:                if (busyWithRollback)
1695:                    return;
1696:                checkActiveTx();
1697:                resetEpcFields();
1698:                try {
1699:                    busyWithRollback = true;
1700:
1701:                    if (synchronizationInstance != null) {
1702:                        synchronizationInstance
1703:                                .afterCompletion(Status.STATUS_ROLLING_BACK);
1704:                    }
1705:
1706:                    try {
1707:                        cache.doRollback(retainValues);
1708:                        sm.rollback();
1709:                    } finally {
1710:                        reset();
1711:                    }
1712:
1713:                    if (synchronizationInstance != null) {
1714:                        synchronizationInstance
1715:                                .afterCompletion(Status.STATUS_ROLLEDBACK);
1716:                    }
1717:
1718:                } catch (Exception e) {
1719:                    fatalReset();
1720:                    if (BindingSupportImpl.getInstance().isOwnException(e)) {
1721:                        throw (RuntimeException) e;
1722:                    } else {
1723:                        throw BindingSupportImpl.getInstance().internal(
1724:                                e.getMessage(), e);
1725:                    }
1726:                } finally {
1727:                    transactionActive = false;
1728:                    busyWithRollback = false;
1729:                }
1730:            }
1731:
1732:            public void setRestoreValues(boolean b) {
1733:                checkPropChange();
1734:                this .restoreValues = b;
1735:            }
1736:
1737:            public boolean getRestoreValues() {
1738:                return restoreValues;
1739:            }
1740:
1741:            /**
1742:             * Check the consistency of all instances in the local cache. Currently
1743:             * this makes sure that all birectional relationships have been completed
1744:             * properly (both sides in sync) but other checks may will be added in
1745:             * future. This method is very slow and should only be used for debugging
1746:             * during development.
1747:             *
1748:             * @see #setCheckModelConsistencyOnCommit(boolean)
1749:             */
1750:            public void checkModelConsistency() {
1751:                cache.checkModelConsistency();
1752:            }
1753:
1754:            /**
1755:             * Add the OID and State for deletion.
1756:             */
1757:            public void addForDelete(OID oid, State state) {
1758:                if (Debug.DEBUG) {
1759:                    // make sure untyped OIDs are not added
1760:                    if (oid.getAvailableClassMetaData() == null) {
1761:                        BindingSupportImpl.getInstance().internal(
1762:                                "oid is untyped: " + oid);
1763:                    }
1764:                }
1765:                toBeDeleted.add(oid, state);
1766:            }
1767:
1768:            /**
1769:             * This calls commit on all the transactional objects. It ensures
1770:             * that the instances undergo the correct state changes.
1771:             */
1772:            public void commit() {
1773:                if (managed) {
1774:                    throw BindingSupportImpl
1775:                            .getInstance()
1776:                            .invalidOperation(
1777:                                    "May not call commit in managed transaction environment");
1778:                }
1779:                if (!transactionActive) {
1780:                    throw BindingSupportImpl.getInstance().invalidOperation(
1781:                            "Transaction is not active");
1782:                }
1783:                internalCommit(false);
1784:            }
1785:
1786:            private void dumpTxDirtyList(String msg) {
1787:                System.out.println("--- txDirtyListHead: " + msg);
1788:                for (PCStateMan o = txDirtyListTail; o != null; o = o.next) {
1789:                    System.out.println(o.pc.getClass().getName()
1790:                            + "@"
1791:                            + Integer
1792:                                    .toHexString(System.identityHashCode(o.pc))
1793:                            + ": " + o.pc);
1794:                }
1795:                System.out.println("---");
1796:            }
1797:
1798:            private void internalCommit(boolean phase) {
1799:                StatesReturned sc = null;
1800:
1801:                if (synchronizationInstance != null) {
1802:                    synchronizationInstance.beforeCompletion();
1803:                    synchronizationInstance
1804:                            .afterCompletion(Status.STATUS_COMMITTING);
1805:                }
1806:
1807:                try {
1808:                    prepareForStore(true);
1809:
1810:                    sc = sm
1811:                            .store(
1812:                                    storeOidStateContainer,
1813:                                    toBeDeleted,
1814:                                    retainValues,
1815:                                    phase ? StorageManager.STORE_OPTION_PREPARE
1816:                                            : StorageManager.STORE_OPTION_COMMIT,
1817:                                    false);
1818:
1819:                    resetEpcFields();
1820:                    updateOIDsAndDoAutoS(sc);
1821:                    cache.doCommit(retainValues);
1822:
1823:                    invokePostStore();
1824:
1825:                    if (!phase) {
1826:
1827:                        if (synchronizationInstance != null) {
1828:                            synchronizationInstance
1829:                                    .afterCompletion(Status.STATUS_COMMITTED);
1830:                        }
1831:
1832:                    }
1833:
1834:                    reset();
1835:                    transactionActive = false;
1836:                } catch (Exception e) {
1837:                    handleException(e);
1838:                } finally {
1839:                    if (sc != null) {
1840:                        sc.clear();
1841:                    }
1842:                }
1843:            }
1844:
1845:            /**
1846:             * Prepare to store all dirty instances for a commit or flush. This finds
1847:             * all reachable instances and invokes preStore lifecycle listeners and
1848:             * jdoPreStore instance callbacks.
1849:             */
1850:            private void prepareForStore(boolean commit) {
1851:                boolean preStoreCalled = false;
1852:                for (PCStateMan i = txDirtyListTail; i != null; i = i.next) {
1853:
1854:                    i.addRefs();
1855:                    preStoreCalled |= i.doJDOPreStore(listeners);
1856:                }
1857:                for (; preStoreCalled;) {
1858:                    PCStateMan root = txDirtyListHead;
1859:                    for (PCStateMan i = txDirtyListTail; i != null; i = i.next) {
1860:
1861:                        i.addRefs();
1862:                    }
1863:                    if (root == txDirtyListHead)
1864:                        break;
1865:                    preStoreCalled = false;
1866:                    for (PCStateMan i = root; i != null; i = i.next) {
1867:                        preStoreCalled |= i.doJDOPreStore(listeners);
1868:                    }
1869:                }
1870:
1871:                storeOidStateContainer.clear();
1872:                toBeDeleted.clear();
1873:                for (PCStateMan i = txDirtyListTail; i != null; i = i.next) {
1874:                    i.prepareCommitOrFlush(commit);
1875:                }
1876:                if (checkModelConsistencyOnCommit) {
1877:                    checkModelConsistency();
1878:                }
1879:
1880:                if (commit) { // fill in the epc stuff
1881:                    storeOidStateContainer.epcAll = epcAll;
1882:                    storeOidStateContainer.epcOids = epcObjectCount > 0 ? modelMetaData
1883:                            .convertToOID(epcObjects, epcObjectCount)
1884:                            : null;
1885:                    storeOidStateContainer.epcClasses = epcClasses;
1886:                    storeOidStateContainer.epcClassCount = epcClassCount;
1887:                }
1888:            }
1889:
1890:            private void invokePostStore() {
1891:                if (listeners != null && listeners.hasPostStoreListeners()) {
1892:                    for (PCStateMan i = txDirtyListTail; i != null; i = i.next) {
1893:                        i.firePostStore(listeners);
1894:                    }
1895:                }
1896:            }
1897:
1898:            /**
1899:             * This flushes everything to the store. After this state interogation
1900:             * will not be correct and the behaviour is not inline with the spec.
1901:             * This is used for big batch procedures that needs to free the memory.
1902:             */
1903:            public void flush() {
1904:                StatesReturned sc = null;
1905:                try {
1906:                    prepareForStore(true);
1907:
1908:                    sc = sm.store(storeOidStateContainer, toBeDeleted, false,
1909:                            StorageManager.STORE_OPTION_FLUSH, true);
1910:
1911:                    updateOIDsAndDoAutoS(sc);
1912:
1913:                    cache.doCommit(retainValues);
1914:
1915:                    invokePostStore();
1916:
1917:                    resetEpcFields();
1918:                    reset();
1919:                } catch (Exception x) {
1920:                    handleException(x);
1921:                } finally {
1922:                    if (sc != null) {
1923:                        sc.clear();
1924:                    }
1925:                }
1926:            }
1927:
1928:            public void flush(boolean retainValues) {
1929:                if (retainValues) {
1930:                    flushRetainState();
1931:                } else {
1932:                    flush();
1933:                }
1934:            }
1935:
1936:            public List versantAllDirtyInstances() {
1937:                if (txDirtyListTail == null)
1938:                    return Collections.EMPTY_LIST;
1939:                List l = new ArrayList();
1940:                for (PCStateMan i = txDirtyListTail; i != null; i = i.next) {
1941:                    l.add(i.pc);
1942:                }
1943:                return l;
1944:            }
1945:
1946:            /**
1947:             * This is used to flush the current changes to the store.
1948:             * All state interogation will still work after this is called.
1949:             * The data is just flushed to the store for queries to work.
1950:             * <p/>
1951:             * The implication of this is that the datastore connection will be pinned
1952:             * to the jdoConnection for the life time of the transaction.
1953:             * <p/>
1954:             * This method will be a no-op if the transaction is not active.
1955:             */
1956:            public void flushRetainState() {
1957:                if (!transactionActive)
1958:                    return;
1959:                StatesReturned sc = null;
1960:
1961:                storeOidStateContainer.clear();
1962:                toBeDeleted.clear();
1963:                try {
1964:                    prepareForStore(false);
1965:
1966:                    if (storeOidStateContainer.isEmpty()
1967:                            && toBeDeleted.size() == 0) {
1968:                        return;
1969:                    }
1970:
1971:                    sc = sm.store(storeOidStateContainer, toBeDeleted, true,
1972:                            StorageManager.STORE_OPTION_FLUSH, false);
1973:
1974:                    updateOIDsAndDoAutoS(sc);
1975:                    for (PCStateMan i = txDirtyListTail; i != null; i = i.next) {
1976:                        i.flushCommit();
1977:                    }
1978:
1979:                    invokePostStore();
1980:
1981:                    storeOidStateContainer.clear();
1982:                    toBeDeleted.clear();
1983:                } catch (Exception x) {
1984:                    handleException(x);
1985:                } finally {
1986:                    try {
1987:                        sc.clear();
1988:                    } catch (Exception e) {
1989:                        //ignore
1990:                    }
1991:                }
1992:            }
1993:
1994:            /**
1995:             * This will do everything except actually commit to the store.
1996:             */
1997:            public void phaseCommit1() {
1998:                internalCommit(true);
1999:            }
2000:
2001:            /**
2002:             * Do the actual commit on the store.
2003:             */
2004:            public void phaseCommit2() {
2005:                sm.commit();
2006:
2007:                if (synchronizationInstance != null) {
2008:                    synchronizationInstance
2009:                            .afterCompletion(Status.STATUS_COMMITTED);
2010:                }
2011:
2012:            }
2013:
2014:            public boolean isActive() {
2015:                return transactionActive;
2016:            }
2017:
2018:            public final boolean isActiveDS() {
2019:                return transactionActive && !optimistic;
2020:            }
2021:
2022:            public void setNontransactionalRead(boolean nontransactionalRead) {
2023:                checkPropChange();
2024:                this .nontransactionalRead = nontransactionalRead;
2025:            }
2026:
2027:            public boolean getNontransactionalRead() {
2028:                return nontransactionalRead;
2029:            }
2030:
2031:            public void setNontransactionalWrite(boolean nontransactionalWrite) {
2032:                checkPropChange();
2033:                this .nontransactionalWrite = nontransactionalWrite;
2034:            }
2035:
2036:            public boolean getNontransactionalWrite() {
2037:                return nontransactionalWrite;
2038:            }
2039:
2040:            public void setRetainValues(boolean retainValues) {
2041:                //        checkPropChange();
2042:                this .retainValues = retainValues;
2043:            }
2044:
2045:            /**
2046:             * Check for changing props in active tx.
2047:             */
2048:            private final void checkPropChange() {
2049:                if (transactionActive) {
2050:                    throw BindingSupportImpl.getInstance().invalidOperation(
2051:                            "May not be changed in active transaction");
2052:                }
2053:            }
2054:
2055:            public boolean getRetainValues() {
2056:                return retainValues;
2057:            }
2058:
2059:            public void setOptimistic(boolean optimistic) {
2060:                checkPropChange();
2061:                this .optimistic = optimistic;
2062:            }
2063:
2064:            public boolean getOptimistic() {
2065:                return optimistic;
2066:            }
2067:
2068:            public void setSynchronization(Synchronization sync) {
2069:                this .synchronizationInstance = sync;
2070:            }
2071:
2072:            public Synchronization getSynchronization() {
2073:                return synchronizationInstance;
2074:            }
2075:
2076:            public PersistenceManager getPersistenceManager() {
2077:                return VersantPersistenceManagerImp.this ;
2078:            }
2079:
2080:            //==================================Transaction imp end=======================
2081:
2082:            /**
2083:             * Create a new oid for a pc instance.
2084:             */
2085:            private NewObjectOID assignOID(PersistenceCapable pc) {
2086:                ClassMetaData cmd = modelMetaData.getClassMetaData(pc
2087:                        .getClass());
2088:                if (cmd == null) {
2089:                    throw BindingSupportImpl.getInstance().invalidOperation(
2090:                            "There is no metadata registered for "
2091:                                    + pc.getClass());
2092:                }
2093:                if (cmd.instancesNotAllowed) {
2094:                    throw BindingSupportImpl.getInstance().invalidOperation(
2095:                            "Instances of " + cmd.qname
2096:                                    + " may not be persistent or managed");
2097:                }
2098:                NewObjectOID oid = cmd.createNewObjectOID();
2099:                oid.init(++counter);
2100:                return oid;
2101:            }
2102:
2103:            /**
2104:             * This is called by the JDOManagedCache when an instance is added
2105:             * but it is not already managed.
2106:             */
2107:            public PCStateMan reManage(OID oid, State state) {
2108:                if (oid.getAvailableClassMetaData() == null) {
2109:                    // replace untyped OID with a real one since we have a state
2110:                    OID tmp = state.getClassMetaData(modelMetaData).createOID(
2111:                            true);
2112:                    tmp.setLongPrimaryKey(oid.getLongPrimaryKey());
2113:                    oid = tmp;
2114:                }
2115:                PCStateMan stateObject = getStateObject();
2116:                stateObject.init(oid, state.getClassMetaData(modelMetaData),
2117:                        state, this );
2118:                return stateObject;
2119:            }
2120:
2121:            private final void reManage(PersistenceCapable pc, OID oid,
2122:                    boolean isTransactional) {
2123:                PCStateMan sm = getStateObject();
2124:                pc.jdoReplaceStateManager(createStateManagerProxy(sm));
2125:                sm.init(pc, oid, isTransactional);
2126:                sm.getRealOIDIfAppId();
2127:
2128:                // check for app identity instance with same pk as instance already in
2129:                // local pm cache
2130:                if (!isTransactional
2131:                        && sm.getClassMetaData().identityType == MDStatics.IDENTITY_TYPE_APPLICATION) {
2132:                    OID realOID = ((NewObjectOID) sm.oid).realOID;
2133:                    if (realOID != null && cache.contains(realOID)) {
2134:
2135:                        // throwing duplicateKey would be problematic for
2136:                        // java, because duplicateKey is fatal
2137:                        throw BindingSupportImpl.getInstance().runtime(
2138:                                "Instance of " + sm.getClassMetaData().qname
2139:                                        + " with identity '" + realOID
2140:                                        + "' already exists in"
2141:                                        + " the local PM cache");
2142:
2143:                    }
2144:                }
2145:
2146:                //The refs to the wrapper is kept around to avoid gc of the instance
2147:                cache.add(sm);
2148:                if (Debug.DEBUG) {
2149:                    if (sm.cacheEntry == null) {
2150:                        throw BindingSupportImpl.getInstance().internal(
2151:                                "cacheEntry must be initialized");
2152:                    }
2153:                }
2154:            }
2155:
2156:            /**
2157:             * Create a proxy for a PCStateMan or return it as is if no proxy is
2158:             * needed. This is used to synchronize StateManager access when
2159:             * multithreading is required.
2160:             */
2161:            public StateManager createStateManagerProxy(PCStateMan sm) {
2162:                if (multithreaded) {
2163:                    return new SynchronizedStateManagerProxy(proxy, sm);
2164:                } else {
2165:                    return sm;
2166:                }
2167:            }
2168:
2169:            /**
2170:             * add an transactional instance to the list.
2171:             *
2172:             * @param stateObject
2173:             */
2174:            public void addTxStateObject(PCStateMan stateObject) {
2175:                if (Debug.DEBUG) {
2176:                    if (!stateObject.isTx()) {
2177:                        throw BindingSupportImpl.getInstance().internal(
2178:                                "The instance is not Transactional");
2179:                    }
2180:                }
2181:
2182:                if (stateObject.isDirty()) {
2183:                    if (!stateObject.isInDirtyList(txDirtyListHead)) {
2184:                        addTxDirty(stateObject);
2185:                    }
2186:                } else {
2187:                    if (stateObject.isInDirtyList(txDirtyListHead)) {
2188:                        removeTxDirty(stateObject);
2189:                    }
2190:                }
2191:            }
2192:
2193:            /**
2194:             * Add pc to the dirty list.
2195:             */
2196:            private void addTxDirty(PCStateMan pc) {
2197:                if (txDirtyListHead == null) {
2198:                    txDirtyListHead = txDirtyListTail = pc;
2199:                    pc.next = null;
2200:                    pc.prev = null;
2201:                } else {
2202:                    pc.prev = txDirtyListHead;
2203:                    txDirtyListHead.next = pc;
2204:                    pc.next = null;
2205:                    txDirtyListHead = pc;
2206:                }
2207:                dirtyCmdBits.add(pc.getClassMetaData());
2208:                pc.inDirtyList = true;
2209:            }
2210:
2211:            /**
2212:             * Remove pc from the dirty list.
2213:             */
2214:            private void removeTxDirty(PCStateMan pc) {
2215:                if (Debug.DEBUG) {
2216:                    if (!pc.isInDirtyList(txDirtyListHead)) {
2217:                        throw BindingSupportImpl.getInstance().internal(
2218:                                "not in dirty list: " + pc);
2219:                    }
2220:                }
2221:                if (txDirtyListTail == pc) {
2222:                    txDirtyListTail = pc.next;
2223:                } else {
2224:                    pc.prev.next = pc.next;
2225:                }
2226:                if (txDirtyListHead == pc) {
2227:                    txDirtyListHead = pc.prev;
2228:                } else {
2229:                    pc.next.prev = pc.prev;
2230:                }
2231:                dirtyCmdBits.remove(pc.getClassMetaData());
2232:            }
2233:
2234:            /**
2235:             * Clear the dirty list.
2236:             */
2237:            public void clearTxDirtyList() {
2238:                for (PCStateMan i = txDirtyListTail; i != null;) {
2239:                    PCStateMan next = i.next;
2240:                    i.prev = null;
2241:                    i.next = null;
2242:                    i = next;
2243:                    dirtyCmdBits.clear();
2244:                }
2245:                txDirtyListHead = txDirtyListTail = null;
2246:            }
2247:
2248:            public void removeTxStateObject(PCStateMan stateObject) {
2249:                if (stateObject.isInDirtyList(txDirtyListHead)) {
2250:                    removeTxDirty(stateObject);
2251:                }
2252:            }
2253:
2254:            private final void reset() {
2255:                storeOidStateContainer.clear();
2256:                clearTxDirtyList();
2257:            }
2258:
2259:            /**
2260:             * This will reset the pm to be returned to the pool.
2261:             */
2262:            public void resetForPooling() {
2263:                if (Debug.DEBUG) {
2264:                    if (transactionActive) {
2265:                        throw BindingSupportImpl.getInstance().fatal(
2266:                                "The tx must be inactive");
2267:                    }
2268:                }
2269:                managed = false;
2270:                cache.clear();
2271:                sm.reset();
2272:                sm.setUserObject(userObject = null);
2273:
2274:                synchronizationInstance = null;
2275:
2276:                resetEpcFields();
2277:                reset();
2278:            }
2279:
2280:            /**
2281:             * Check to see if the pm has not been closed by the user.
2282:             */
2283:            private void checkClosed() {
2284:                checkInPool();
2285:                if (closed) {
2286:                    throw BindingSupportImpl.getInstance().invalidOperation(
2287:
2288:                    "The 'PersistenceManager' is already closed");
2289:
2290:                }
2291:            }
2292:
2293:            public PersistenceManager getPersistenceManager(
2294:                    PersistenceCapable pc) {
2295:                return this ;
2296:            }
2297:
2298:            private PCStateMan getStateObject() {
2299:                return new PCStateMan(cache, modelMetaData, proxy);
2300:            }
2301:
2302:            //    public Collection mapFrom(Object data, Class cls) {
2303:            //        if (data instanceof ResultSet) {
2304:            //            return null;
2305:            //        } else {
2306:            //            throw BindingSupportImpl.getInstance().unsupported();
2307:            //        }
2308:            //    }
2309:            //
2310:            //    public Collection mapFrom(Object data, Class cls, String[] customMapping) {
2311:            //        if (data instanceof ResultSet) {
2312:            //            return null;
2313:            //        } else {
2314:            //            throw BindingSupportImpl.getInstance().unsupported();
2315:            //        }
2316:            //    }
2317:
2318:            //============================debug methods ============================================================================
2319:
2320:            public boolean isPNonTx(Object pc) {
2321:                return pmPreCheck(pc).isPNonTx();
2322:            }
2323:
2324:            public boolean isPClean(Object pc) {
2325:                return pmPreCheck(pc).isPClean();
2326:            }
2327:
2328:            public boolean isPNew(Object pc) {
2329:                return pmPreCheck(pc).isPNew();
2330:            }
2331:
2332:            public boolean isPNewDeleted(Object pc) {
2333:                return pmPreCheck(pc).isPNewDeleted();
2334:            }
2335:
2336:            public boolean isPDeleted(Object pc) {
2337:                return pmPreCheck(pc).isPDeleted();
2338:            }
2339:
2340:            public boolean isTClean(Object pc) {
2341:                return pmPreCheck(pc).isTClean();
2342:            }
2343:
2344:            public boolean isTDirty(Object pc) {
2345:                return pmPreCheck(pc).isTDirty();
2346:            }
2347:
2348:            public boolean isPDirty(Object pc) {
2349:                return pmPreCheck(pc).isPDirty();
2350:            }
2351:
2352:            /**
2353:             * Return the internal oid representation for this pc instance.
2354:             * This oid is the actual oid and not a clone. If pc is null then null
2355:             * is returned.
2356:             */
2357:            public OID getInternalOID(final PersistenceCapable pc) {
2358:                if (pc == null)
2359:                    return null;
2360:                return getInternalSM(pc).oid;
2361:            }
2362:
2363:            /**
2364:             * This is used internally to obtain the PCStateObject for a PersistanceCapable
2365:             * instance. This instance must be managed by this pm.
2366:             */
2367:            public PCStateMan getInternalSM(final PersistenceCapable pc) {
2368:                if (pc == null)
2369:                    return null;
2370:                requestedPCState = null;
2371:                pc.jdoGetPersistenceManager();
2372:                if (requestedPCState == null) {
2373:                    throw BindingSupportImpl.getInstance().internal(
2374:                            "Instance not managed: "
2375:                                    + pc.getClass().getName()
2376:                                    + "@"
2377:                                    + Integer.toHexString(System
2378:                                            .identityHashCode(pc)) + ": "
2379:                                    + pc.toString());
2380:                }
2381:                return requestedPCState;
2382:            }
2383:
2384:            public PCStateMan getSMIfManaged(PersistenceCapable pc) {
2385:                if (pc == null)
2386:                    return null;
2387:                requestedPCState = null;
2388:                pc.jdoGetPersistenceManager();
2389:                return requestedPCState;
2390:            }
2391:
2392:            /**
2393:             * This is used internally to obtain the PCStateObject for a PersistanceCapable
2394:             * instance. This instance must be managed by this pm.
2395:             */
2396:            public PCStateMan getInternalSM(OID oid) {
2397:                if (oid == null)
2398:                    return null;
2399:                return getInternalSM((PersistenceCapable) getObjectById(oid,
2400:                        false));
2401:            }
2402:
2403:            /**
2404:             * This is used for debug. Not to be used else where.
2405:             */
2406:            public State getInternaleState(PersistenceCapable pc) {
2407:                PCStateMan pcState = getInternalSM(pc);
2408:                if (pcState == null)
2409:                    return null;
2410:                return pcState.state;
2411:            }
2412:
2413:            public void dump(OID oid) {
2414:                if (Debug.DEBUG) {
2415:                    PCStateMan pcStateObject = cache.getByOID(oid, true);
2416:                    if (pcStateObject != null) {
2417:                        pcStateObject.dump();
2418:                    } else {
2419:                        if (Debug.DEBUG) {
2420:                            Debug.OUT.println("######## null for dump#######");
2421:                        }
2422:                    }
2423:                }
2424:            }
2425:
2426:            /**
2427:             * Are there any dirty instances?
2428:             */
2429:            public boolean isDirty() {
2430:                return txDirtyListHead != null;
2431:            }
2432:
2433:            /**
2434:             * This is used from getObjectByID where the object by id is not in the managed cache.
2435:             * If there there is no jdo instance for the supplied instance then null is returned.
2436:             *
2437:             * @param ignoreLocalPmCache This is used to indicate that we should not check the
2438:             *                           if the state is in the localCache on the serverside. The serverSide might
2439:             *                           have a ref to the local cache.
2440:             */
2441:            private PCStateMan getStateMan(OID aOID, int fgIndex, int fieldNo,
2442:                    int navClassIndex, boolean ignoreLocalPmCache) {
2443:                StatesReturned container = null;
2444:                try {
2445:                    container = getStateJdoConnection(aOID, null, fgIndex, aOID
2446:                            .getAvailableClassId(), ignoreLocalPmCache,
2447:                            fieldNo, navClassIndex);
2448:
2449:                    if (Debug.DEBUG) {
2450:                        if (container.get(container.getDirectOID()) == NULLState.NULL_STATE) {
2451:                            //this instance does not exist in db
2452:                            if (container.size() != 1) {
2453:                                throw BindingSupportImpl
2454:                                        .getInstance()
2455:                                        .internal(
2456:                                                "Then directOid of the container is null "
2457:                                                        + "so there should not be any other instances");
2458:                            }
2459:                        }
2460:                    }
2461:
2462:                    return addAndReturnFirstDirect(container);
2463:                } finally {
2464:                    if (container != null)
2465:                        container.clear();
2466:                }
2467:            }
2468:
2469:            /**
2470:             * This translates the old JDOConnection style call into a StorageManager
2471:             * call. It should be nuked at some point.
2472:             */
2473:            private StatesReturned getStateJdoConnection(OID oid,
2474:                    State current, int fetchGroup, int classId,
2475:                    boolean ignoreLocalPmCache, int fieldNo, int navClassIndex) {
2476:                // todo use ignoreLocalPmCache to modify context
2477:
2478:                if (classId < 0)
2479:                    classId = oid.getAvailableClassId();
2480:                ClassMetaData cmd = oid.getAvailableClassMetaData();
2481:                FetchGroup fg = cmd == null ? null : cmd.getFetchGroup(
2482:                        fetchGroup, classId);
2483:
2484:                FieldMetaData triggerField;
2485:                if (navClassIndex >= 0) { // navigated stateFieldNo
2486:                    ClassMetaData navCmd = modelMetaData.classes[navClassIndex];
2487:                    triggerField = navCmd.stateFields[fieldNo];
2488:                } else if (fieldNo >= 0 && cmd != null) { // missing absFieldNo
2489:                    triggerField = cmd.stateFields[cmd.absToRel[fieldNo]];
2490:                } else {
2491:                    triggerField = null;
2492:                }
2493:
2494:                return sm.fetch(this , oid, current, fg, triggerField);
2495:            }
2496:
2497:            /**
2498:             * This is called by sm's if they require a field. This will update the
2499:             * local cache with the requested data (State instances). The returned
2500:             * container reference must be kept until all the required State instances
2501:             * in the local cache have been referenced or they might be GCed.
2502:             * This is important for collections of PC and other fields that
2503:             * involve fetching State instances and loading them into the local cache.
2504:             * They are only hard referenced when the SCO instance has been created.
2505:             */
2506:            public StatesReturned getState(OID oid, State current, int fgi,
2507:                    int fieldNo, int navClassIndex, boolean ignoreLocalPmCache) {
2508:                StatesReturned container = getStateJdoConnection(oid,
2509:                        current == null || current.isEmpty() ? null : current,
2510:                        fgi, oid.getAvailableClassId(), ignoreLocalPmCache,
2511:                        fieldNo, navClassIndex);
2512:
2513:                if (Debug.DEBUG) {
2514:                    if (container.get(container.getDirectOID()) == NULLState.NULL_STATE) {
2515:                        //this instance does not exist in db
2516:                        if (container.size() != 1) {
2517:                            throw BindingSupportImpl
2518:                                    .getInstance()
2519:                                    .internal(
2520:                                            "Then directOid of the container is null "
2521:                                                    + "so there should not be any other instances");
2522:                        }
2523:                    }
2524:                }
2525:                addToCache(container);
2526:                return container;
2527:            }
2528:
2529:            /**
2530:             * This is called by sm's when doing a refresh. It will ensure that the
2531:             * data comes from the database when in a datastore transaction.
2532:             */
2533:            public void getStateForRefresh(OID oid, State current, int fgi) {
2534:                StatesReturned container = null;
2535:                try {
2536:                    container = getStateJdoConnection(oid, current == null
2537:                            || current.isEmpty() ? null : current, fgi, oid
2538:                            .getAvailableClassId(), true, -1, -1);
2539:                    addToCache(container);
2540:                } finally {
2541:                    if (container != null)
2542:                        container.clear();
2543:                }
2544:            }
2545:
2546:            private void fillCacheWith(OIDArray oids, int fgi,
2547:                    int stateFieldNo, int navClassIndex) {
2548:                StatesReturned container = null;
2549:                try {
2550:                    FieldMetaData triggerField;
2551:                    if (navClassIndex >= 0) { // navigated stateFieldNo
2552:                        ClassMetaData navCmd = modelMetaData.classes[navClassIndex];
2553:                        triggerField = navCmd.stateFields[stateFieldNo];
2554:                    } else {
2555:                        triggerField = null;
2556:                    }
2557:                    container = sm.fetch(this , oids, triggerField);
2558:                    addToCache(container);
2559:                } finally {
2560:                    if (container != null)
2561:                        container.clear();
2562:                }
2563:            }
2564:
2565:            /**
2566:             * This is the pm is not the current PM.
2567:             */
2568:            private static final void checkPM(PersistenceManager otherPM,
2569:                    PersistenceManager currentPM) {
2570:                if (otherPM != null && otherPM != currentPM) {
2571:                    throw BindingSupportImpl
2572:                            .getInstance()
2573:                            .invalidOperation(
2574:                                    "The instance is not managed by this PersistenceManager");
2575:                }
2576:            }
2577:
2578:            private static final PersistenceCapable checkPersCapable(Object o) {
2579:                try {
2580:                    return (PersistenceCapable) o;
2581:                } catch (ClassCastException e) {
2582:                    throw BindingSupportImpl.getInstance().invalidOperation(
2583:                            "The supplied instance is not of type "
2584:                                    + PersistenceCapable.class.getName() + " ("
2585:                                    + o.getClass().getName() + ")");
2586:                }
2587:            }
2588:
2589:            /**
2590:             * <<<<<<< VersantPersistenceManagerImp.java
2591:             * This util method is used by collection types to preload their pc
2592:             * entries. It tests to determine if the states refered to by the oids is
2593:             * in the managed cache. If not they must be bulk loaded from server.
2594:             * The scenario in which this is likely to happen is when the collection
2595:             * is not in the default fetch group and the state is in cache with the
2596:             * collection filled in. If this collection field is read then the
2597:             * pcstateman will determine that the stateField is filled and hence not
2598:             * ask the server for it.
2599:             */
2600:            public void checkToPreFetch(Object[] oids, int stateFieldNo,
2601:                    int navClassIndex) {
2602:                if (oids != null && oids.length > 0 && oids[0] != null
2603:                        && cache.getByOID((OID) oids[0], true) == null) {
2604:                    OIDArray oidArray = new OIDArray();
2605:                    for (int i = 0; i < oids.length && oids[i] != null; i++) {
2606:                        oidArray.add((OID) oids[i]);
2607:                    }
2608:                    fillCacheWith(oidArray, 0, stateFieldNo, navClassIndex);
2609:                }
2610:            }
2611:
2612:            /**
2613:             * This does general exception handling. It ensures that a rollback
2614:             * is done for Fatal exceptions.
2615:             * CR:
2616:             * If called with an instance of JDOUserException it's a no-op
2617:             * and the passed instance is thrown.
2618:             */
2619:            private final void handleException(Exception x) {
2620:                if (BindingSupportImpl.getInstance().isOwnFatalException(x)
2621:                        && isActive()) {
2622:                    try {
2623:                        rollbackImp();
2624:                    } catch (Exception e) {
2625:                        // discard as we are already busy processing an earlier
2626:                        // exception
2627:                    }
2628:                }
2629:                if (BindingSupportImpl.getInstance().isOwnInternalException(x)) {
2630:                    fatalReset();
2631:                    throw (RuntimeException) x;
2632:                } else if (BindingSupportImpl.getInstance().isOwnException(x)) {
2633:                    throw (RuntimeException) x;
2634:                } else {
2635:                    fatalReset();
2636:                    throw BindingSupportImpl.getInstance().internal(
2637:                            x.getMessage(), x);
2638:                }
2639:            }
2640:
2641:            /**
2642:             * Convert all PC, VersantOid and objectid-class params to OIDs. This
2643:             * makes it possible to pass an OID instead of a PC instance for PC
2644:             * parameters.
2645:             */
2646:            public void convertPcParamsToOID(Object[] params) {
2647:                if (params == null)
2648:                    return;
2649:                int n = params.length;
2650:                for (int i = 0; i < n; i++) {
2651:                    Object param = params[i];
2652:                    if (param == null)
2653:                        continue;
2654:                    if (param instanceof  Collection) {
2655:                        List l = new ArrayList((Collection) param);
2656:                        for (int j = 0; j < l.size(); j++) {
2657:                            Object o = (Object) l.get(j);
2658:                            o = convertPcParamsToOIDImp(o, i);
2659:                            if (o instanceof  OID) {
2660:                                l.set(j, o);
2661:                            }
2662:                        }
2663:                        params[i] = l;
2664:                    } else {
2665:                        params[i] = convertPcParamsToOIDImp(param, i);
2666:                    }
2667:                }
2668:            }
2669:
2670:            private Object convertPcParamsToOIDImp(Object param, int paramIndex) {
2671:                if (param == null)
2672:                    return param;
2673:                if (param instanceof  PersistenceCapable) {
2674:                    PersistenceCapable pc = (PersistenceCapable) param;
2675:                    if (pc.jdoGetPersistenceManager() != proxy) {
2676:                        if (pc.jdoGetPersistenceManager() != null) {
2677:                            throw BindingSupportImpl
2678:                                    .getInstance()
2679:                                    .invalidOperation(
2680:                                            "PC parameter "
2681:                                                    + paramIndex
2682:                                                    + " is managed by "
2683:                                                    + pc
2684:                                                            .jdoGetPersistenceManager()
2685:                                                    + " (this is " + proxy
2686:                                                    + "): " + pc.getClass()
2687:                                                    + ": " + Utils.toString(pc));
2688:                        } else {
2689:                            throw BindingSupportImpl.getInstance()
2690:                                    .invalidOperation(
2691:                                            "PC parameter " + paramIndex
2692:                                                    + " is transient: "
2693:                                                    + pc.getClass() + ": "
2694:                                                    + Utils.toString(pc));
2695:                        }
2696:                    }
2697:                    param = getInternalOID((PersistenceCapable) param);
2698:                } else if (param instanceof  VersantOid) {
2699:                    // datastore identity OID parameter
2700:                    OID oid = modelMetaData
2701:                            .convertJDOGenieOIDtoOID((VersantOid) param);
2702:                    param = convertNewToActual(oid);
2703:                } else {
2704:                    ClassMetaData cmd = modelMetaData
2705:                            .getClassMetaDataForObjectIdClass(param.getClass());
2706:                    if (cmd != null) { // app identity objectid-class parameter
2707:                        OID oid = cmd.createOID(false);
2708:                        oid.fillFromPK(param);
2709:                        param = oid;
2710:                    }
2711:                }
2712:                return param;
2713:            }
2714:
2715:            //==========================XAResource impl==================================
2716:
2717:            private int txTimeout = 3000;
2718:            private Xid xid = null;
2719:
2720:            private int txState;
2721:            public static final int TX_INACTIVE = 0;
2722:            public static final int TX_STARTED = 1;
2723:            public static final int TX_FAIL = 2;
2724:            public static final int TX_PREPARED = 4;
2725:            public static final int TX_SUSPENDED = 8;
2726:
2727:            /**
2728:             * If the pm is managed by a TransactionManager.
2729:             */
2730:            private boolean managed;
2731:            /**
2732:             * This is a flag to indicate if it was closed by the client in a managed env.
2733:             */
2734:            private boolean managedClosed = false;
2735:
2736:            /**
2737:             * Is this pm managed by a container.
2738:             *
2739:             * @return
2740:             */
2741:            public boolean isManaged() {
2742:                return managed;
2743:            }
2744:
2745:            /**
2746:             * set the state of the pm to be in a container.
2747:             *
2748:             * @param managed
2749:             */
2750:            public void setManaged(boolean managed) {
2751:                this .managed = managed;
2752:                this .managedClosed = false;
2753:            }
2754:
2755:            /**
2756:             * Called to associate the resource with a transaction.
2757:             * <p/>
2758:             * If the flags argument is {@link #TMNOFLAGS}, the transaction must not
2759:             * previously have been seen by this resource manager, or an
2760:             * {@link javax.transaction.xa.XAException} with error code XAER_DUPID will be thrown.
2761:             * <p/>
2762:             * If the flags argument is {@link #TMJOIN}, the resource will join a
2763:             * transaction previously seen by its resource manager.
2764:             * <p/>
2765:             * If the flags argument is {@link #TMRESUME} the resource will
2766:             * resume the transaction association that was suspended with
2767:             * end(TMSUSPEND).
2768:             *
2769:             * @param xid   The id of the transaction to associate with.
2770:             * @param flags Must be either {@link #TMNOFLAGS}, {@link #TMJOIN}
2771:             *              or {@link #TMRESUME}.
2772:             * @throws javax.transaction.xa.XAException
2773:             *          If an error occurred.
2774:             */
2775:
2776:            public void start(Xid xid, int flags) throws XAException {
2777:                if (Debug.DEBUG) {
2778:                    Debug.OUT
2779:                            .println("***** JdoGeniePersistenceManagerImp.start ***** flag = "
2780:                                    + getFlagString(flags) + " for \n" + this );
2781:                    System.out.println("xid = " + xid);
2782:                }
2783:                checkInPool();
2784:                switch (flags) {
2785:                case TMNOFLAGS:
2786:                case TMJOIN:
2787:                    begin(xid);
2788:                    break;
2789:                case TMRESUME:
2790:                    if (checkId(xid)) {
2791:                        resume(xid);
2792:                    }
2793:                    break;
2794:                default:
2795:                    throw new XAException(
2796:                            "Unsupported state for method start state = "
2797:                                    + flags);
2798:                }
2799:            }
2800:
2801:            private boolean checkId(Xid xid) {
2802:                if (!this .xid.equals(xid)) {
2803:                    //            throw new JDOFatalInternalException("The check id failed");
2804:                    return false;
2805:                }
2806:                return true;
2807:            }
2808:
2809:            private void resume(Xid xid) throws XAException {
2810:                checkInPool();
2811:                if (this .txState != TX_SUSPENDED) {
2812:                    throw new XAException(
2813:                            "Could resume a transaction that was not suspended");
2814:                }
2815:                this .txState = TX_STARTED;
2816:            }
2817:
2818:            private void begin(Xid xid) throws XAException {
2819:                checkInPool();
2820:                if (this .txState == TX_INACTIVE) {
2821:                    this .xid = xid;
2822:                    try {
2823:                        beginImp();
2824:                        this .txState = TX_STARTED;
2825:                    } catch (Exception e) {
2826:                        throw new XAException(
2827:                                "Could not begin a transaction : "
2828:                                        + e.getMessage());
2829:                    }
2830:                } else if (this .txState == TX_STARTED
2831:                        || this .txState == TX_PREPARED
2832:                        || this .txState == TX_SUSPENDED) {
2833:                    // Transaction on this pm has started already. Since beans will 
2834:                    // share this pm, there will be multple calls to begin.        
2835:                    return;
2836:                } else {
2837:                    throw new XAException(
2838:                            "Could not begin a transaction in state = "
2839:                                    + txState);
2840:                }
2841:            }
2842:
2843:            /**
2844:             * Prepare to commit the work done on this resource in the given
2845:             * transaction.
2846:             * <p/>
2847:             * This method cannot return a status indicating that the transaction
2848:             * should be rolled back. If the resource wants the transaction to
2849:             * be rolled back, it should throw an <code>XAException</code> at the
2850:             * caller.
2851:             *
2852:             * @param xid The id of the transaction to prepare to commit work for.
2853:             * @return Either {@link #XA_OK} or {@link #XA_RDONLY}.
2854:             * @throws javax.transaction.xa.XAException
2855:             *          If an error occurred.
2856:             */
2857:
2858:            public int prepare(Xid xid) throws XAException {
2859:                if (Debug.DEBUG) {
2860:                    Debug.OUT
2861:                            .println("***** JdoGeniePersistenceManagerImp.prepare *****");
2862:                }
2863:                checkInPool();
2864:                if (checkId(xid)) {
2865:                    if (txState == TX_STARTED) {
2866:                        try {
2867:                            internalCommit(true);
2868:                            this .txState = TX_PREPARED;
2869:                            return XA_OK;
2870:                        } catch (Exception ex) {
2871:                            ex.printStackTrace();
2872:                            throw new XAException("Could not prepare commit : "
2873:                                    + ex.getMessage());
2874:                        }
2875:                    } else if (this .txState == TX_PREPARED
2876:                            || this .txState == TX_SUSPENDED) {
2877:                        return XA_OK;
2878:                    } else {
2879:                        throw new XAException(
2880:                                "Wrong state to commit phase one on : state = "
2881:                                        + this .txState);
2882:                    }
2883:                }
2884:                return XA_OK;
2885:            }
2886:
2887:            /**
2888:             * Commit the work done on this resource in the given transaction.
2889:             * <p/>
2890:             * If the <code>onePhase</code> argument is true, one-phase
2891:             * optimization is being used, and the {@link #prepare(Xid) prepare}
2892:             * method must not have been called for this transaction.
2893:             * Otherwise, this is the second phase of the two-phase commit protocol.
2894:             *
2895:             * @param xid      The id of the transaction to commit work for.
2896:             * @param onePhase If true, the transaction manager is using one-phase
2897:             *                 optimization.
2898:             * @throws javax.transaction.xa.XAException
2899:             *          If an error occurred.
2900:             */
2901:
2902:            public void commit(Xid xid, boolean onePhase) throws XAException {
2903:                if (Debug.DEBUG) {
2904:                    Debug.OUT
2905:                            .println("***** JdoGeniePersistenceManagerImp.commit ***** onePhase: "
2906:                                    + onePhase + " for \n" + this );
2907:                }
2908:                checkInPool();
2909:                if (checkId(xid)) {
2910:                    try {
2911:                        if (onePhase && txState == TX_STARTED) {
2912:                            internalCommit(false);
2913:                        } else if (this .txState == TX_PREPARED) {
2914:                            phaseCommit2();
2915:                        } else if (this .txState == TX_INACTIVE) {
2916:                            return;
2917:                        } else {
2918:                            throw new XAException(
2919:                                    "Unable to commit unexpected state: state = "
2920:                                            + txState + " for xid = " + xid);
2921:                        }
2922:
2923:                        this .txState = TX_INACTIVE;
2924:                        this .xid = null;
2925:                    } catch (XAException ex) {
2926:                        ex.printStackTrace();
2927:                        throw ex;
2928:                    } catch (Exception ex) {
2929:                        ex.printStackTrace();
2930:                        throw new XAException("Could not commit : "
2931:                                + ex.getMessage());
2932:                    }
2933:                }
2934:            }
2935:
2936:            private void checkInPool() {
2937:                if (inPool) {
2938:                    throw BindingSupportImpl.getInstance().fatal(
2939:                            "The pm is in the pool");
2940:                }
2941:            }
2942:
2943:            public boolean isInTx() {
2944:                return this .txState != TX_INACTIVE;
2945:            }
2946:
2947:            /**
2948:             * Roll back the work done on this resource in the given transaction.
2949:             *
2950:             * @param xid The id of the transaction to rollback for.
2951:             * @throws javax.transaction.xa.XAException
2952:             *          If an error occurred.
2953:             */
2954:
2955:            public void rollback(Xid xid) throws XAException {
2956:                if (Debug.DEBUG) {
2957:                    Debug.OUT
2958:                            .println("***** JdoGeniePersistenceManagerImp.rollback *****");
2959:                }
2960:                checkInPool();
2961:                if (checkId(xid)) {
2962:                    try {
2963:                        if (this .txState != TX_INACTIVE) {
2964:                            rollbackImp();
2965:                            this .txState = TX_INACTIVE;
2966:                        }
2967:                        this .xid = null;
2968:                    } catch (Exception e) {
2969:                        throw new XAException("Could not rollback: "
2970:                                + e.getMessage());
2971:                    }
2972:                }
2973:            }
2974:
2975:            /**
2976:             * Called to disassociate the resource from a transaction.
2977:             * <p/>
2978:             * If the flags argument is {@link #TMSUCCESS}, the portion of work
2979:             * was done sucessfully.
2980:             * <p/>
2981:             * If the flags argument is {@link #TMFAIL}, the portion of work
2982:             * failed. The resource manager may mark the transaction for
2983:             * rollback only to avoid the transaction being committed.
2984:             * <p/>
2985:             * If the flags argument is {@link #TMSUSPEND} the resource will
2986:             * temporarily suspend the transaction association. The transaction
2987:             * must later be re-associated by giving the {@link #TMRESUME} state
2988:             * to the {@link #start(Xid,int) start} method.
2989:             *
2990:             * @param xid   The id of the transaction to disassociate from.
2991:             * @param flags Must be either {@link #TMSUCCESS}, {@link #TMFAIL}
2992:             *              or {@link #TMSUSPEND}.
2993:             * @throws javax.transaction.xa.XAException
2994:             *          If an error occurred.
2995:             */
2996:
2997:            public void end(Xid xid, int flags) throws XAException {
2998:                if (Debug.DEBUG) {
2999:                    Debug.OUT
3000:                            .println("***** JdoGeniePersistenceManagerImp.end ***** flag: "
3001:                                    + getFlagString(flags) + " for \n" + this );
3002:                    System.out.println("xid = " + xid);
3003:                }
3004:                checkInPool();
3005:                if (checkId(xid)) {
3006:                    switch (flags) {
3007:                    case TMSUCCESS:
3008:                        this .txState = TX_STARTED;
3009:                        break;
3010:                    case TMFAIL:
3011:                        this .txState = TX_FAIL;
3012:                        break;
3013:                    case TMSUSPEND:
3014:                        this .txState = TX_SUSPENDED;
3015:                        break;
3016:                    default:
3017:                        throw new XAException("Unable to end transaction = "
3018:                                + xid + " unhandled flag = " + flags);
3019:                    }
3020:                }
3021:            }
3022:
3023:            private String getFlagString(int flag) {
3024:                switch (flag) {
3025:                case 8388608:
3026:                    return "TMENDRSCAN";
3027:                case 536870912:
3028:                    return "TMFAIL";
3029:                case 2097152:
3030:                    return "TMJOIN";
3031:                case 0:
3032:                    return "TMNOFLAGS";
3033:                case 1073741824:
3034:                    return "TMONEPHASE";
3035:                case 134217728:
3036:                    return "TMRESUME";
3037:                case 16777216:
3038:                    return "TMSTARTRSCAN";
3039:                case 67108864:
3040:                    return "TMSUCCESS";
3041:                case 33554432:
3042:                    return "TMSUSPEND";
3043:                default:
3044:                    return "UNKNOWN";
3045:                }
3046:            }
3047:
3048:            /**
3049:             * Tells the resource manager to forget about a heuristic decision.
3050:             *
3051:             * @param xid The id of the transaction that was ended with a heuristic
3052:             *            decision.
3053:             * @throws javax.transaction.xa.XAException
3054:             *          If an error occurred.
3055:             */
3056:
3057:            public void forget(Xid xid) throws XAException {
3058:                if (Debug.DEBUG) {
3059:                    Debug.OUT
3060:                            .println("***** JdoGeniePersistenceManagerImp.forget *****");
3061:                }
3062:                checkInPool();
3063:                if (this .xid.equals(xid)) {
3064:                    this .txState = TX_STARTED;
3065:                }
3066:            }
3067:
3068:            /**
3069:             * Get the current transaction timeout value for this resource.
3070:             *
3071:             * @return The current timeout value, in seconds.
3072:             * @throws javax.transaction.xa.XAException
3073:             *          If an error occurred.
3074:             */
3075:
3076:            public int getTransactionTimeout() throws XAException {
3077:                if (Debug.DEBUG) {
3078:                    Debug.OUT
3079:                            .println("***** JdoGeniePersistenceManagerImp.getTransactionTimeout *****");
3080:                }
3081:                checkInPool();
3082:                return txTimeout;
3083:            }
3084:
3085:            /**
3086:             * This method does not check for inPool because Weblogic seems to keep
3087:             * a ref around of used ones to try and re-use it. This happens even though
3088:             * it was delisted from transaction.
3089:             * <p/>
3090:             * Tells the caller if this resource has the same resource manager
3091:             * as the argument resource.
3092:             * <p/>
3093:             * The transaction manager needs this method to be able to decide
3094:             * if the {@link #start(Xid,int) start} method should be given the
3095:             * {@link #TMJOIN} state.
3096:             *
3097:             * @throws javax.transaction.xa.XAException
3098:             *          If an error occurred.
3099:             */
3100:
3101:            public boolean isSameRM(XAResource xaResource) throws XAException {
3102:                if (Debug.DEBUG) {
3103:                    Debug.OUT
3104:                            .println("***** JdoGeniePersistenceManagerImp.isSameRM *****");
3105:                    Debug.OUT.println("***** isSame: this = " + this );
3106:                    Debug.OUT.println("***** isSame: other = " + this );
3107:                }
3108:                return xaResource == this ;
3109:            }
3110:
3111:            /**
3112:             * Return a list of transactions that are in a prepared or heuristically
3113:             * state.
3114:             * <p/>
3115:             * This method looks not only at the resource it is invoked on, but
3116:             * also on all other resources managed by the same resource manager.
3117:             * It is intended to be used by the application server when recovering
3118:             * after a server crash.
3119:             * <p/>
3120:             * A recovery scan is done with one or more calls to this method.
3121:             * At the first call, {@link #TMSTARTRSCAN} must be in the
3122:             * <code>state</code> argument to indicate that the scan should be started.
3123:             * During the recovery scan, the resource manager maintains an internal
3124:             * cursor that keeps track of the progress of the recovery scan.
3125:             * To end the recovery scan, the {@link #TMENDRSCAN} must be passed
3126:             * in the <code>state</code> argument.
3127:             *
3128:             * @param flag Must be either {@link #TMNOFLAGS}, {@link #TMSTARTRSCAN},
3129:             *             {@link #TMENDRSCAN} or <code>TMSTARTRSCAN|TMENDRSCAN</code>.
3130:             * @return An array of zero or more transaction ids.
3131:             * @throws javax.transaction.xa.XAException
3132:             *          If an error occurred.
3133:             */
3134:
3135:            public Xid[] recover(int flag) throws XAException {
3136:                if (Debug.DEBUG) {
3137:                    Debug.OUT
3138:                            .println("***** JdoGeniePersistenceManagerImp.recover ***** flag = "
3139:                                    + getFlagString(flag));
3140:                }
3141:                checkInPool();
3142:                Xid[] xids = txState == TX_PREPARED ? new Xid[] { xid } : null;
3143:                return xids;
3144:            }
3145:
3146:            /**
3147:             * Set the transaction timeout value for this resource.
3148:             * <p/>
3149:             * If the <code>seconds</code> argument is <code>0</code>, the
3150:             * timeout value is set to the default timeout value of the resource
3151:             * manager.
3152:             * <p/>
3153:             * Not all resource managers support setting the timeout value.
3154:             * If the resource manager does not support setting the timeout
3155:             * value, it should return false.
3156:             *
3157:             * @param seconds The timeout value, in seconds.
3158:             * @return True if the timeout value could be set, otherwise false.
3159:             * @throws javax.transaction.xa.XAException
3160:             *          If an error occurred.
3161:             */
3162:
3163:            public boolean setTransactionTimeout(int seconds)
3164:                    throws XAException {
3165:                if (Debug.DEBUG) {
3166:                    Debug.OUT
3167:                            .println("***** JdoGeniePersistenceManagerImp.setTransactionTimeout *****");
3168:                }
3169:                checkInPool();
3170:                if (seconds < -1) {
3171:                    return false;
3172:                } else {
3173:                    this .txTimeout = seconds;
3174:                }
3175:                return true;
3176:            }
3177:
3178:            //====================Synchronization imp==============================
3179:
3180:            public void afterCompletion(int status) {
3181:                if (Debug.DEBUG) {
3182:                    Debug.OUT
3183:                            .println("***** JdoGeniePersistenceManagerImp.afterCompletion *****");
3184:                }
3185:                proxy.resetPM();
3186:                pmf.pmClosedNotification(this , false, false);
3187:            }
3188:
3189:            public void beforeCompletion() {
3190:                if (Debug.DEBUG) {
3191:                    Debug.OUT
3192:                            .println("***** JdoGeniePersistenceManagerImp.beforeCompletion *****");
3193:                }
3194:            }
3195:
3196:            /**
3197:             * Set the locking mode for datastore transactions. This method may only
3198:             * be called when no transaction is active. You can set the default value
3199:             * for this property using the Workbench or edit your .jdogenie file
3200:             * directly (datastore.tx.locking property).
3201:             *
3202:             * @see #LOCKING_NONE
3203:             * @see #LOCKING_FIRST
3204:             * @see #LOCKING_ALL
3205:             */
3206:            public void setDatastoreTxLocking(int mode) {
3207:                int policy;
3208:                switch (mode) {
3209:                case VersantPersistenceManager.LOCKING_NONE:
3210:                    policy = StorageManager.LOCK_POLICY_NONE;
3211:                    break;
3212:                case VersantPersistenceManager.LOCKING_FIRST:
3213:                    policy = StorageManager.LOCK_POLICY_FIRST;
3214:                    break;
3215:                case VersantPersistenceManager.LOCKING_ALL:
3216:                    policy = StorageManager.LOCK_POLICY_ALL;
3217:                    break;
3218:                default:
3219:                    throw BindingSupportImpl.getInstance().invalidOperation(
3220:                            "Invalid datastoreTxLocking mode: " + mode);
3221:                }
3222:                sm.setLockingPolicy(policy);
3223:            }
3224:
3225:            /**
3226:             * Get the locking mode for datastore transactions.
3227:             */
3228:            public int getDatastoreTxLocking() {
3229:                switch (sm.getLockingPolicy()) {
3230:                case StorageManager.LOCK_POLICY_NONE:
3231:                    return VersantPersistenceManager.LOCKING_NONE;
3232:                case StorageManager.LOCK_POLICY_FIRST:
3233:                    return VersantPersistenceManager.LOCKING_FIRST;
3234:                case StorageManager.LOCK_POLICY_ALL:
3235:                    return VersantPersistenceManager.LOCKING_ALL;
3236:                }
3237:                return VersantPersistenceManager.LOCKING_NONE;
3238:            }
3239:
3240:            public void logEvent(int level, String description, int ms) {
3241:                sm.logEvent(level, description, ms);
3242:            }
3243:
3244:            /**
3245:             * Return the instance for oid if it is present in the local PM cache
3246:             * otherwise return null. Note that the instances might still be hollow
3247:             * and touching its fields will cause a fetch from the level 2 cache
3248:             * or database.
3249:             *
3250:             * @see #isHollow(Object)
3251:             */
3252:            public Object getObjectByIdFromCache(Object oid) {
3253:                if (oid == null) {
3254:                    throw BindingSupportImpl.getInstance().invalidOperation(
3255:                            "The oid is null");
3256:                }
3257:                try {
3258:                    PCStateMan stateMan = cache.getByOID(extractOID(oid), true);
3259:                    return stateMan == null ? null : stateMan.pc;
3260:                } catch (Exception e) {
3261:                    handleException(e);
3262:                    return null;
3263:                }
3264:            }
3265:
3266:            /**
3267:             * Is the instance hollow? Hollow instances are managed but their fields
3268:             * have not been loaded from the level 2 cache or database.
3269:             *
3270:             * @see #getObjectByIdFromCache(Object)
3271:             */
3272:            public boolean isHollow(Object pc) {
3273:                PCStateMan pcStateObject = pmPreCheck(pc);
3274:                return pcStateObject != null && pcStateObject.isHollow();
3275:            }
3276:
3277:            /**
3278:             * Does the instance have an identity? New instances are only assigned
3279:             * an identity on commit or flush or when the application executes an
3280:             * operation that requires the identity.
3281:             */
3282:            public boolean hasIdentity(Object pc) {
3283:                return !pmPreCheck(pc).oid.isNew();
3284:            }
3285:
3286:            /**
3287:             * Process the ReferenceQueue for the local cache. This is called when
3288:             * a query fetches data from the server to ensure that long running
3289:             * read-only transactions do not leak SoftReferences.
3290:             */
3291:            public void processLocalCacheReferenceQueue() {
3292:                cache.processReferenceQueue();
3293:            }
3294:
3295:            /**
3296:             * This method makes detached copies of the parameter instances and returns
3297:             * the copies as the result of the method. The order of instances in the
3298:             * parameter Collection's iteration corresponds to the order of corresponding
3299:             * instances in the returned Collection's iteration.
3300:             * <p/>
3301:             * The Collection of instances is first made persistent, and the reachability
3302:             * algorithm is run on the instances. This ensures that the closure of all
3303:             * of the instances in the the parameter Collection is persistent.
3304:             * <p/>
3305:             * For each instance in the parameter Collection, a corresponding detached
3306:             * copy is created. Each field in the persistent instance is handled based on
3307:             * its type and whether the field is contained in the fetch group for the
3308:             * persistence-capable class. If there are duplicates in the parameter
3309:             * Collection, the corresponding detached copy is used for each such duplicate.
3310:             */
3311:            public Collection versantDetachCopy(Collection pcs,
3312:                    String fetchGroup) {
3313:                if (pcs instanceof  QueryResult) {
3314:                    //this is done to resolve the queryresult to avoid extra queries
3315:                    // when iterating over it
3316:                    pcs.size();
3317:                }
3318:
3319:                if (fetchGroup == null)
3320:                    fetchGroup = FetchGroup.DFG_NAME;
3321:                for (Iterator pcIt = pcs.iterator(); pcIt.hasNext();) {
3322:                    Object o = pcIt.next();
3323:                    if (o == null || !(o instanceof  VersantDetachable))
3324:                        continue;
3325:                    VersantDetachable pc = (VersantDetachable) o;
3326:                    requestedPCState = null;
3327:                    pc.jdoGetPersistenceManager();
3328:                    if (requestedPCState == null) {
3329:                        makePersistent(pc);
3330:                    }
3331:                }
3332:                flushRetainState();
3333:                // load the container with the initial root collection
3334:                DetachStateContainer dsc = new DetachStateContainer(this );
3335:                for (Iterator pcIt = pcs.iterator(); pcIt.hasNext();) {
3336:                    PersistenceCapable pc = (PersistenceCapable) pcIt.next();
3337:                    if (pc == null)
3338:                        continue;
3339:                    PCStateMan sm = getInternalSM(pc);
3340:                    ClassMetaData cmd = sm.state
3341:                            .getClassMetaData(modelMetaData);
3342:                    FetchGroup fg = cmd.getFetchGroup(fetchGroup);
3343:                    if (fg == null) {
3344:                        fg = cmd.fetchGroups[0];
3345:                    }
3346:                    dsc.add(sm.oid, sm.state, fg);
3347:                }
3348:
3349:                // find all states reachable via the fetch group
3350:                for (; dsc.hasNextFetchGroup();) {
3351:                    State state = dsc.getNextFetchGroupState();
3352:                    FetchGroup fg = dsc.getNextFetchGroup();
3353:                    OID oid = dsc.getNextFetchGroupOID();
3354:
3355:                    // if we have to load the fetch group then there is no need to check
3356:                    // any of its fields - all of the States referenced by the fetch
3357:                    // group will have been added to the StatesReturned on the
3358:                    // server and will be added to our dcs
3359:                    if (!oid.isNew()
3360:                            && (state == null || !state.containsFetchGroup(fg))) {
3361:                        StatesReturned con = getStateForDetach(oid, fg.index);
3362:                        addToDetachStateContainer(con, dsc);
3363:                        state = con.get(oid);
3364:                        addToCache(con);
3365:                        dsc.add(oid, state, fg);
3366:                    }
3367:                    ClassMetaData cmd = state.getClassMetaData(modelMetaData);
3368:                    state.addFetchGroupStatesToDCS(fg, dsc, this , oid, cmd);
3369:                }
3370:                dsc.createPcClasses(modelMetaData);
3371:                ArrayList copyList = new ArrayList(pcs.size());
3372:                for (Iterator pcIt = pcs.iterator(); pcIt.hasNext();) {
3373:                    Object o = pcIt.next();
3374:                    if (o == null || !(o instanceof  VersantDetachable)) {
3375:                        copyList.add(null);
3376:                        continue;
3377:                    }
3378:                    VersantDetachable pc = (VersantDetachable) o;
3379:                    requestedPCState = null;
3380:                    pc.jdoGetPersistenceManager();
3381:                    if (requestedPCState == null) {
3382:                        copyList.add(pc);
3383:                    }
3384:                    copyList.add(dsc.getDetachCopy(pc));
3385:                }
3386:                return copyList;
3387:            }
3388:
3389:            public List versantCollectReachable(Collection roots,
3390:                    String fetchGroup) {
3391:                if (fetchGroup == null) {
3392:                    fetchGroup = FetchGroup.REF_NAME;
3393:                }
3394:                checkActiveTx();
3395:
3396:                Set result = new HashSet();
3397:                List todo = new ArrayList(roots);
3398:
3399:                while (todo.size() > 0) // non-recursive!
3400:                {
3401:                    Object o = todo.remove(0);
3402:                    String currentFetchGroup = fetchGroup;
3403:                    if (o instanceof  Object[]) { // added by sm.collectReachable
3404:                        Object[] tmp = (Object[]) o;
3405:                        currentFetchGroup = (String) tmp[1];
3406:                        o = tmp[0];
3407:                    }
3408:
3409:                    if (o == null || !(o instanceof  PersistenceCapable))
3410:                        continue;
3411:                    PersistenceCapable pc = (PersistenceCapable) o;
3412:
3413:                    requestedPCState = null;
3414:                    pc.jdoGetPersistenceManager();
3415:                    if (requestedPCState == null) {
3416:                        makePersistent(pc);
3417:                    }
3418:                    PCStateMan sm = pmPreCheck(pc);
3419:                    if (!result.contains(sm) && !sm.isDeleted(pc)) {
3420:                        if (currentFetchGroup != null)
3421:                        // nextFetchGroup was defined for the referencing field
3422:                        {
3423:                            sm.collectReachable(currentFetchGroup, todo);
3424:                        }
3425:                        result.add(sm);
3426:                    }
3427:                }
3428:                List pcresult = new ArrayList();
3429:                for (Iterator it = result.iterator(); it.hasNext();) {
3430:                    pcresult.add(((PCStateMan) it.next()).pc);
3431:                }
3432:                return pcresult;
3433:            }
3434:
3435:            /**
3436:             * This is called by sm's if they require a field.
3437:             * This will update the managedCache with the requested data.
3438:             */
3439:            public StatesReturned getStateForDetach(OID oid, int fgi) {
3440:                return getStateJdoConnection(oid, null, fgi, oid
3441:                        .getAvailableClassId(), false, -1, -1);
3442:            }
3443:
3444:            public State getStateFromLocalCacheById(Object oid) {
3445:                if (oid == null) {
3446:                    throw BindingSupportImpl.getInstance().invalidOperation(
3447:                            "The supplied oid is null");
3448:                }
3449:                try {
3450:                    OID nOID = extractOID(oid);
3451:                    PCStateMan stateMan = cache.getByOID(nOID, true);
3452:                    if (stateMan == null) {
3453:                        return null;
3454:                    }
3455:                    return stateMan.state;
3456:                } catch (Exception e) {
3457:                    handleException(e);
3458:                    return null;
3459:                }
3460:            }
3461:
3462:            /**
3463:             * This util method is used by collection types to preload their pc
3464:             * entries. It tests to determine if the states refered to by the oids is
3465:             * in the managed cache. If not they must be bulk loaded from server.
3466:             * The scenario in which this is likely to happen is when the collection
3467:             * is not in the default fetch group and the state is in cache with the
3468:             * collection filled in. If this collection field is read then the
3469:             * pcstateman will determine that the stateField is filled and hence not
3470:             * ask the server for it.
3471:             */
3472:            public int getObjectsById(Object[] oids, int length, Object[] data,
3473:                    int stateFieldNo, int classMetaDataIndex) {
3474:                if (oids == null || oids.length <= 0)
3475:                    return 0;
3476:                OIDArray oidArray = new OIDArray();
3477:                for (int i = 0; i < length; i++) {
3478:                    Object o = oids[i];
3479:                    //            if (o == null) {
3480:                    //                length = i;
3481:                    //                break;
3482:                    //            }
3483:                    if (!(o instanceof  OID)) {
3484:                        data[i] = o;
3485:                        continue;
3486:                    }
3487:                    OID oid = (OID) o;
3488:                    PCStateMan pcStateMan = cache.getByOID(oid, true);
3489:                    if (pcStateMan != null) {
3490:                        data[i] = pcStateMan.pc;
3491:                    } else {
3492:                        oidArray.add(oid);
3493:                        data[i] = null;
3494:                    }
3495:                }
3496:                if (!oidArray.isEmpty()) {
3497:                    FieldMetaData triggerField;
3498:                    if (classMetaDataIndex >= 0) { // navigated stateFieldNo
3499:                        ClassMetaData navCmd = modelMetaData.classes[classMetaDataIndex];
3500:                        triggerField = navCmd.stateFields[stateFieldNo];
3501:                    } else {
3502:                        triggerField = null;
3503:                    }
3504:                    StatesReturned container = sm.fetch(this , oidArray,
3505:                            triggerField);
3506:                    // keep a reference to each of the returned PCStateMan's so
3507:                    // that they are not GCed before we reference them
3508:                    PCStateMan[] nogc = addToCacheAndManage(container);
3509:                    for (int i = 0; i < length; i++) {
3510:                        if (data[i] == null) {
3511:                            data[i] = cache.getByOID((OID) oids[i], true).pc;
3512:                        }
3513:                    }
3514:                    if (nogc == null) {
3515:                        // dummy code to keep IDE happy and to hopefully prevent
3516:                        // any overzealous optimization from removing nogc
3517:                    }
3518:                }
3519:                return length;
3520:            }
3521:
3522:            /**
3523:             * Construct a new query instance with the given candidate class from a
3524:             * named query. The query name given must be the name of a query defined
3525:             * in metadata. The metadata is searched for the specified name.
3526:             * This is a JDO 2 preview feature.
3527:             */
3528:            public Query versantNewNamedQuery(Class cls, String queryName) {
3529:                try {
3530:                    ClassMetaData cmd = modelMetaData.getClassMetaData(cls);
3531:                    if (cmd == null) {
3532:                        throw BindingSupportImpl.getInstance()
3533:                                .invalidOperation(
3534:                                        "Class " + cls.getName()
3535:                                                + " is not persistent");
3536:                    }
3537:                    QueryDetails qp = cmd.getNamedQuery(queryName);
3538:                    if (qp == null) {
3539:                        throw BindingSupportImpl
3540:                                .getInstance()
3541:                                .invalidOperation(
3542:                                        "No query called '"
3543:                                                + queryName
3544:                                                + "' has been defined in the meta data for Class "
3545:                                                + cmd.qname);
3546:                    }
3547:                    return new VersantQueryImp(proxy, qp);
3548:                } catch (Exception e) {
3549:                    handleException(e);
3550:                    return null;
3551:                }
3552:            }
3553:
3554:            /**
3555:             * Must bidirectional relationships be checked for consistency
3556:             * on commit or flush?
3557:             */
3558:            public boolean isCheckModelConsistencyOnCommit() {
3559:                return checkModelConsistencyOnCommit;
3560:            }
3561:
3562:            public void setCheckModelConsistencyOnCommit(boolean on) {
3563:                this .checkModelConsistencyOnCommit = on;
3564:            }
3565:
3566:            /**
3567:             * This method applies the changes contained in the collection of detached
3568:             * instances to the corresponding persistent instances in the cache and
3569:             * returns a collection of persistent instances that exactly corresponds to
3570:             * the parameter instances. The order of instances in the parameter
3571:             * Collection's iteration corresponds to the order of corresponding
3572:             * instances in the returned Collection's iteration.
3573:             * <p/>
3574:             * Changes made to instances while detached are applied to the corresponding
3575:             * persistent instances in the cache. New instances associated with the
3576:             * detached instances are added to the persistent instances in the
3577:             * corresponding place.
3578:             */
3579:            public Collection versantAttachCopy(Collection detached,
3580:                    boolean makeTransactional) {
3581:                return versantAttachCopy(detached, makeTransactional, false);
3582:            }
3583:
3584:            /**
3585:             * This method applies the changes contained in the collection of detached
3586:             * instances to the corresponding persistent instances in the cache and
3587:             * returns a collection of persistent instances that exactly corresponds to
3588:             * the parameter instances. The order of instances in the parameter
3589:             * Collection's iteration corresponds to the order of corresponding
3590:             * instances in the returned Collection's iteration.
3591:             * <p/>
3592:             * Changes made to instances while detached are applied to the corresponding
3593:             * persistent instances in the cache. New instances associated with the
3594:             * detached instances are added to the persistent instances in the
3595:             * corresponding place.
3596:             *
3597:             * @param detached VersantDetachable objects to attach in the current
3598:             *                 transaction
3599:             * @param shallow  attach only the objects in 'detached' Collection and not
3600:             *                 reachable objects if true.
3601:             */
3602:            public Collection versantAttachCopy(Collection detached,
3603:                    boolean makeTransactional, boolean shallow) {
3604:                AttachStateContainer asc = new AttachStateContainer(this );
3605:                for (Iterator pcIt = detached.iterator(); pcIt.hasNext();) {
3606:                    VersantDetachable detachable = (VersantDetachable) pcIt
3607:                            .next();
3608:                    if (detachable == null)
3609:                        continue;
3610:                    asc.addVersantDetachable(detachable);
3611:                }
3612:                if (!shallow) {
3613:                    AttachNavStateManager ansm = new AttachNavStateManager(asc);
3614:                    for (int c = 0; c < asc.getDetachedSize(); c++) {
3615:                        VersantDetachable detachable = asc
3616:                                .getVersantDetachable(c);
3617:                        if (detachable.jdoGetPersistenceManager() != null)
3618:                            continue;
3619:                        detachable.jdoReplaceStateManager(ansm);
3620:                        ClassMetaData cmd = modelMetaData
3621:                                .getClassMetaData(detachable.getClass());
3622:                        for (; cmd != null; cmd = cmd.pcSuperMetaData) {
3623:                            for (int i = 0; i < cmd.fields.length; i++) {
3624:                                FieldMetaData field = cmd.fields[i];
3625:                                if (field.fake)
3626:                                    continue;
3627:                                switch (field.category) {
3628:                                case FieldMetaData.CATEGORY_REF:
3629:                                case FieldMetaData.CATEGORY_POLYREF:
3630:                                case FieldMetaData.CATEGORY_COLLECTION:
3631:                                case FieldMetaData.CATEGORY_MAP:
3632:                                case FieldMetaData.CATEGORY_ARRAY:
3633:                                    detachable
3634:                                            .jdoProvideField(field.managedFieldNo);
3635:                                }
3636:                            }
3637:                        }
3638:                    }
3639:                }
3640:
3641:                AttachCopyStateManager acsm = new AttachCopyStateManager(this );
3642:                for (int c = 0; c < asc.getDetachedSize(); c++) {
3643:                    OID oid = asc.getOID(c);
3644:                    VersantDetachable detachable = asc.getVersantDetachable(c);
3645:                    if (detachable.jdoGetPersistenceManager() != null)
3646:                        continue;
3647:                    boolean notNew = !oid.isNew();
3648:                    if (notNew && !detachable.versantIsDirty())
3649:                        continue;
3650:                    detachable.jdoReplaceStateManager(acsm);
3651:                    PCStateMan sm = getInternalSM(oid);
3652:                    if (notNew && sm.state.isHollow()) {
3653:                        StatesReturned con = getStateForDetach(oid, 0);
3654:                        addToCache(con);
3655:                    }
3656:                    acsm.setState(sm.state);
3657:                    if (notNew) {
3658:                        Object dVersion = detachable.versantGetVersion();
3659:                        Object aVersion = sm.getOptimisticLockingValue();
3660:                        if (aVersion == null
3661:                                && sm.getClassMetaData().optimisticLockingField != null) {
3662:                            throw BindingSupportImpl.getInstance().internal(
3663:                                    "Optimistic locking value not available for "
3664:                                            + sm.getClassMetaData().qname);
3665:                        }
3666:                        if (aVersion != null && !aVersion.equals(dVersion)) {
3667:                            throw BindingSupportImpl
3668:                                    .getInstance()
3669:                                    .concurrentUpdate(
3670:                                            "The object ("
3671:                                                    + oid.toStringImp()
3672:                                                    + ") has been updated since its been detached "
3673:                                                    + "(current='" + aVersion
3674:                                                    + "', detached='"
3675:                                                    + dVersion + "')", oid);
3676:                        }
3677:                    }
3678:                    ClassMetaData cmd = modelMetaData
3679:                            .getClassMetaData(detachable.getClass());
3680:                    for (; cmd != null; cmd = cmd.pcSuperMetaData) {
3681:                        for (int i = 0; i < cmd.fields.length; i++) {
3682:                            FieldMetaData fmd = cmd.fields[i];
3683:                            if (fmd.fake)
3684:                                continue;
3685:                            if (notNew
3686:                                    && !detachable.versantIsDirty(fmd
3687:                                            .getManagedFieldNo())) {
3688:                                continue;
3689:                            }
3690:                            switch (fmd.category) {
3691:                            case FieldMetaData.CATEGORY_SIMPLE:
3692:                            case FieldMetaData.CATEGORY_POLYREF:
3693:                            case FieldMetaData.CATEGORY_EXTERNALIZED:
3694:                            case FieldMetaData.CATEGORY_REF:
3695:                            case FieldMetaData.CATEGORY_COLLECTION:
3696:                            case FieldMetaData.CATEGORY_ARRAY:
3697:                            case FieldMetaData.CATEGORY_MAP:
3698:                                acsm.setFieldMetaData(fmd);
3699:                                int managedFieldNo = fmd.managedFieldNo;
3700:                                detachable.jdoProvideField(managedFieldNo);
3701:                                if (notNew) {
3702:                                    sm.makeDirty(detachable, managedFieldNo);
3703:                                }
3704:                            }
3705:                        }
3706:                    }
3707:                    if (notNew) {
3708:                        sm.resetLoadedFields();
3709:                        sm.setLoadRequired();
3710:                    }
3711:                }
3712:                Collection deleted = asc.getDeleted();
3713:                for (Iterator it = deleted.iterator(); it.hasNext();) {
3714:                    try {
3715:                        Object o = getObjectById(it.next(), true);
3716:                        deletePersistent(o);
3717:                    } catch (JDOObjectNotFoundException e) {
3718:                        // Do Nothing
3719:                    }
3720:                }
3721:                ArrayList attached = new ArrayList();
3722:                for (Iterator pcIt = detached.iterator(); pcIt.hasNext();) {
3723:                    VersantDetachable pc = (VersantDetachable) pcIt.next();
3724:                    if (pc == null) {
3725:                        attached.add(pc);
3726:                        continue;
3727:                    }
3728:                    Object newPC = getObjectById(getOID(pc), false);
3729:                    attached.add(newPC);
3730:                }
3731:                return attached;
3732:            }
3733:
3734:            OID getOID(VersantDetachable detachable) {
3735:                Object oid = detachable.versantGetOID();
3736:                if (oid == null) {
3737:                    PersistenceManager pm = detachable
3738:                            .jdoGetPersistenceManager();
3739:                    if (pm != null) {
3740:                        if (pm instanceof  PMProxy) {
3741:                            pm = ((PMProxy) pm).getRealPM();
3742:                        }
3743:                        if (pm instanceof  VersantPersistenceManagerImp) {
3744:                            OID internalOID = ((VersantPersistenceManagerImp) pm)
3745:                                    .getInternalOID(detachable);
3746:                            detachable
3747:                                    .versantSetOID(getExternalOID(internalOID));
3748:                            return internalOID;
3749:                        } else {
3750:                            throw BindingSupportImpl
3751:                                    .getInstance()
3752:                                    .runtime(
3753:                                            "Can't attach a managed "
3754:                                                    + "instance that is not managed by Versant Open Access");
3755:                        }
3756:                    }
3757:                    PCStateMan sm = getStateObject();
3758:                    NewObjectOID nOID = assignOID(detachable);
3759:                    sm.init(detachable, nOID, this );
3760:                    cache.add(sm);
3761:                    detachable.versantSetOID(nOID);
3762:                    return sm.oid.getAvailableOID();
3763:                } else {
3764:                    return extractOID(oid);
3765:                }
3766:            }
3767:
3768:            final PCStateMan getStateManager(Object o) {
3769:                return cache.getByOID(extractOID(((PersistenceCapable) o)
3770:                        .jdoGetObjectId()), false);
3771:            }
3772:
3773:            final PCStateMan getStateManagerById(Object oid) {
3774:                return cache.getByOID(extractOID(oid), false);
3775:            }
3776:
3777:            public void setRetainConnectionInOptTx(boolean on) {
3778:                sm
3779:                        .setConnectionPolicy(on ? StorageManager.CON_POLICY_PIN_FOR_TX
3780:                                : StorageManager.CON_POLICY_RELEASE);
3781:            }
3782:
3783:            /**
3784:             * Clear all epc fields.
3785:             */
3786:            private void resetEpcFields() {
3787:                epcAll = false;
3788:                epcObjects = null;
3789:                epcObjectCount = 0;
3790:                epcClasses = null;
3791:                epcClassCount = 0;
3792:                epcClassPresent = null;
3793:            }
3794:
3795:            public void evictFromL2CacheAfterCommit(Object o) {
3796:                checkActiveTx();
3797:                evictFromL2CacheAfterCommitImp(o);
3798:            }
3799:
3800:            /**
3801:             * Version of {@link #evictFromL2CacheAfterCommit} without the active tx
3802:             * check for interna use.
3803:             */
3804:            public void evictFromL2CacheAfterCommitImp(Object o) {
3805:                if (epcAll)
3806:                    return;
3807:                if (o instanceof  PersistenceCapable) {
3808:                    PCStateMan sm = pmPreCheck((PersistenceCapable) o);
3809:                    if (sm == null || sm.isNew(null)) {
3810:                        return; // no need to evict transient or new objects
3811:                    }
3812:                    o = sm.oid;
3813:                }
3814:                if (epcObjects == null) {
3815:                    epcObjects = new Object[4];
3816:                } else if (epcObjectCount == epcObjects.length) {
3817:                    Object[] a = new Object[epcObjects.length * 3 / 2 + 1];
3818:                    System.arraycopy(epcObjects, 0, a, 0, epcObjects.length);
3819:                    epcObjects = a;
3820:                }
3821:                epcObjects[epcObjectCount++] = o;
3822:            }
3823:
3824:            public void evictAllFromL2CacheAfterCommit(final Object[] data) {
3825:                checkActiveTx();
3826:                int n = data.length;
3827:                if (n == 0 || epcAll)
3828:                    return;
3829:                ensureCapacityEpcObjects(n);
3830:                for (int i = 0; i < n; i++) {
3831:                    Object o = data[i];
3832:                    if (o instanceof  PersistenceCapable) {
3833:                        PCStateMan sm = pmPreCheck((PersistenceCapable) o);
3834:                        if (sm == null || sm.isNew(null)) {
3835:                            continue; // no need to evict transient or new objects
3836:                        }
3837:                        o = sm.oid;
3838:                    }
3839:                    epcObjects[epcObjectCount++] = o;
3840:                }
3841:            }
3842:
3843:            public void evictAllFromL2CacheAfterCommit(final Collection data) {
3844:                checkActiveTx();
3845:                int n = data.size();
3846:                if (n == 0 || epcAll)
3847:                    return;
3848:                ensureCapacityEpcObjects(n);
3849:                for (Iterator i = data.iterator(); i.hasNext();) {
3850:                    Object o = i.next();
3851:                    if (o instanceof  PersistenceCapable) {
3852:                        PCStateMan sm = pmPreCheck((PersistenceCapable) o);
3853:                        if (sm == null || sm.isNew(null)) {
3854:                            continue; // no need to evict transient or new objects
3855:                        }
3856:                        o = sm.oid;
3857:                    }
3858:                    epcObjects[epcObjectCount++] = o;
3859:                }
3860:            }
3861:
3862:            private void ensureCapacityEpcObjects(int delta) {
3863:                if (epcObjects == null) {
3864:                    epcObjects = new Object[delta + 4];
3865:                } else if (epcObjectCount + delta >= epcObjects.length) {
3866:                    Object[] a = new Object[epcObjectCount + delta];
3867:                    System.arraycopy(epcObjects, 0, a, 0, epcObjects.length);
3868:                    epcObjects = a;
3869:                }
3870:            }
3871:
3872:            public void evictAllFromL2CacheAfterCommit(final Class cls,
3873:                    final boolean includeSubclasses) {
3874:                checkActiveTx();
3875:                ClassMetaData cmd = modelMetaData.getClassMetaData(cls);
3876:                if (cmd == null) {
3877:                    BindingSupportImpl.getInstance().runtime(
3878:                            "Class is not persistent: " + cls);
3879:                }
3880:                evictAllFromL2CacheAfterCommitImp(cmd, includeSubclasses);
3881:            }
3882:
3883:            private void evictAllFromL2CacheAfterCommitImp(ClassMetaData cmd,
3884:                    final boolean includeSubclasses) {
3885:                if (epcAll)
3886:                    return;
3887:                if (epcClasses == null) {
3888:                    epcClasses = new int[4];
3889:                    epcClassPresent = new boolean[modelMetaData.classes.length];
3890:                }
3891:                int ci = cmd.index;
3892:                if (!epcClassPresent[ci]) {
3893:                    if (epcClassCount == epcClasses.length) {
3894:                        int[] a = new int[epcClasses.length * 2];
3895:                        System
3896:                                .arraycopy(epcClasses, 0, a, 0,
3897:                                        epcClasses.length);
3898:                        epcClasses = a;
3899:                    }
3900:                    epcClasses[epcClassCount++] = ci;
3901:                    epcClassPresent[ci] = true;
3902:                }
3903:                if (includeSubclasses) {
3904:                    ClassMetaData[] subs = cmd.pcSubclasses;
3905:                    if (subs != null) {
3906:                        for (int i = subs.length - 1; i >= 0; i--) {
3907:                            evictAllFromL2CacheAfterCommitImp(subs[i],
3908:                                    includeSubclasses);
3909:                        }
3910:                    }
3911:                }
3912:            }
3913:
3914:            public void evictAllFromL2CacheAfterCommit() {
3915:                checkActiveTx();
3916:                epcAll = true;
3917:                epcObjects = null;
3918:                epcObjectCount = 0;
3919:                epcClasses = null;
3920:                epcClassCount = 0;
3921:                epcClassPresent = null;
3922:            }
3923:
3924:            public Object getOptimisticLockingValue(Object o) {
3925:                return getInternalSM((PersistenceCapable) o)
3926:                        .getOptimisticLockingValue();
3927:            }
3928:
3929:            public void setListeners(LifecycleListenerManager listeners) {
3930:                this .listeners = listeners;
3931:            }
3932:
3933:            public void addLifecycleListener(LifecycleListener listener,
3934:                    Class[] classes) {
3935:                if (classes != null) {
3936:                    BindingSupportImpl
3937:                            .getInstance()
3938:                            .runtime(
3939:                                    "Support for non-null "
3940:                                            + "classes parameter has not been implemented");
3941:                }
3942:                if (listeners == null) {
3943:                    listeners = new LifecycleListenerManager(listener);
3944:                } else {
3945:                    listeners = listeners.add(listener);
3946:                }
3947:            }
3948:
3949:            public void removeLifecycleListener(LifecycleListener listener) {
3950:                if (listeners == null) {
3951:                    return;
3952:                }
3953:                listeners = listeners.remove(listener);
3954:            }
3955:
3956:            /**
3957:             * Fire a delete to all of the LifecycleListener's for o.
3958:             */
3959:            public void fireDelete(ClassMetaData cmd, Object o) {
3960:                if (listeners != null) {
3961:                    listeners.fireDelete(o);
3962:                }
3963:            }
3964:
3965:            /**
3966:             * Get our StorageManager.
3967:             */
3968:            public StorageManager getStorageManager() {
3969:                return sm;
3970:            }
3971:
3972:            public LocalPMCache getCache() {
3973:                return cache;
3974:            }
3975:
3976:            public void setCache(LocalPMCache cache) {
3977:                this .cache = cache;
3978:            }
3979:
3980:            public MemQueryCompiler getMemQueryCompiler() {
3981:                return memQueryCompiler;
3982:            }
3983:
3984:            public Reference getActiveReference() {
3985:                return activeReference;
3986:            }
3987:
3988:            public void setActiveReference(Reference activeReference) {
3989:                this .activeReference = activeReference;
3990:            }
3991:
3992:            /**
3993:             * Iterate through all the oid-state pairs returned from the server
3994:             * for a store operation and update the local states.
3995:             * This will also bring back real oids for new oids involved.
3996:             */
3997:            private void updateOIDsAndDoAutoS(StatesReturned container) {
3998:                for (Iterator i = container.iterator(); i.hasNext();) {
3999:                    EntrySet.Entry e = (EntrySet.Entry) i.next();
4000:                    OID oid = (OID) e.getKey();
4001:                    State state = (State) e.getValue();
4002:
4003:                    // This gets the sm with the oid from the container.
4004:                    // This is done for the case of a newOID which is not
4005:                    // mapped in the cache via its real oid.
4006:                    // The sm may not be null because the only way for it to have been sent
4007:                    // to the server for commit was if it was dirty and hence we must have
4008:                    // a hard refs to it.
4009:                    PCStateMan sm;
4010:                    if (oid instanceof  NewObjectOID) {
4011:                        sm = cache.getByNewObjectOID((NewObjectOID) oid);
4012:                        if (sm == null) {
4013:                            sm = cache.getByOID(oid, false);
4014:                            if (sm == null)
4015:                                continue;
4016:                        } else {
4017:                            ((NewObjectOID) sm.oid)
4018:                                    .setRealOid(oid.getRealOID());
4019:                        }
4020:                    } else {
4021:                        sm = cache.getByOID(oid, false);
4022:                        if (sm == null)
4023:                            continue;
4024:                    }
4025:
4026:                    // if the state returned is not null then it contains auto set fields that
4027:                    // needs must be updated the sm's current state.
4028:                    // this must only happen if retainValues is set to true and the state
4029:                    // contains autoset fields. version number is a autoset field.
4030:                    if (state != null) {
4031:                        sm.updateAutoFields(state);
4032:                    }
4033:                }
4034:            }
4035:
4036:            /**
4037:             * Add all the OIDs and States in the container to the cache.
4038:             */
4039:            public void addToCache(StatesReturned container) {
4040:                for (Iterator i = container.iterator(); i.hasNext();) {
4041:                    EntrySet.Entry e = (EntrySet.Entry) i.next();
4042:                    cache.addStateOnly((OID) e.getKey(), (State) e.getValue());
4043:                }
4044:            }
4045:
4046:            /**
4047:             * Add all the OIDs and States in the container to the cache. The
4048:             * PCStateMan's are kept and returned to prevent the new instances
4049:             * being GCed before they are referenced.
4050:             */
4051:            private PCStateMan[] addToCacheAndManage(StatesReturned container) {
4052:                PCStateMan[] smArray = new PCStateMan[1];
4053:                PCStateMan[] ans = new PCStateMan[container.size()];
4054:                int c = 0;
4055:                for (Iterator i = container.iterator(); i.hasNext();) {
4056:                    EntrySet.Entry e = (EntrySet.Entry) i.next();
4057:                    ans[c++] = cache.add((OID) e.getKey(),
4058:                            (State) e.getValue(), smArray);
4059:                }
4060:                return ans;
4061:            }
4062:
4063:            /**
4064:             * Add all the OIDs and States in the container to the cache and return
4065:             * the PCStateMan for the first direct State. This method is specifically written
4066:             * to keep a hard ref to created sm so that it can not be gc'd before it is returned.
4067:             */
4068:            private PCStateMan addAndReturnFirstDirect(StatesReturned container) {
4069:                OID firstDirectOID = container.getDirectOID();
4070:                if (firstDirectOID == null) {
4071:                    return null;
4072:                }
4073:                PCStateMan[] sm = new PCStateMan[1];
4074:                cache.add(firstDirectOID, container.get(firstDirectOID), sm);
4075:                for (Iterator i = container.iterator(); i.hasNext();) {
4076:                    EntrySet.Entry e = (EntrySet.Entry) i.next();
4077:                    cache.addStateOnly((OID) e.getKey(), (State) e.getValue());
4078:                }
4079:                return sm[0];
4080:            }
4081:
4082:            /**
4083:             * Add all the OIDs and States in the container to dcs.
4084:             */
4085:            private void addToDetachStateContainer(StatesReturned container,
4086:                    DetachStateContainer dcs) {
4087:                for (Iterator i = container.iterator(); i.hasNext();) {
4088:                    EntrySet.Entry e = (EntrySet.Entry) i.next();
4089:                    dcs.add((OID) e.getKey(), (State) e.getValue());
4090:                }
4091:            }
4092:
4093:            /**
4094:             * The StorageManager calls this method to check if we need prefetched
4095:             * data or not.
4096:             */
4097:            public boolean isStateRequired(OID oid, FetchGroup fetchGroup) {
4098:                State state = cache.getStateByOID(oid);
4099:                if (state != null) {
4100:                    if (fetchGroup == null) {
4101:                        fetchGroup = state.getClassMetaData().fetchGroups[0];
4102:                    }
4103:                    return !state.containsFetchGroup(fetchGroup);
4104:                }
4105:                return true;
4106:            }
4107:
4108:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.