KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > sessions > AbstractSession


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.sessions;
23
24 import java.util.*;
25 import java.io.*;
26 import oracle.toplink.essentials.descriptors.ClassDescriptor;
27 import oracle.toplink.essentials.internal.helper.*;
28 import oracle.toplink.essentials.platform.server.ServerPlatform;
29 import oracle.toplink.essentials.queryframework.*;
30 import oracle.toplink.essentials.expressions.*;
31 import oracle.toplink.essentials.internal.identitymaps.*;
32 import oracle.toplink.essentials.internal.descriptors.*;
33 import oracle.toplink.essentials.internal.databaseaccess.*;
34 import oracle.toplink.essentials.exceptions.*;
35 import oracle.toplink.essentials.sessions.*;
36 import oracle.toplink.essentials.internal.sequencing.Sequencing;
37 import oracle.toplink.essentials.logging.*;
38 import oracle.toplink.essentials.internal.sessions.AbstractRecord;
39 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
40 import oracle.toplink.essentials.internal.helper.ConcurrencyManager;
41 import oracle.toplink.essentials.internal.helper.IdentityHashtable;
42
43 /**
44  * Implementation of oracle.toplink.essentials.sessions.Session
45  * The public interface should be used by public API and testing, the implementation should be used internally.
46  * @see oracle.toplink.essentials.sessions.Session
47  *
48  * <p>
49  * <b>Purpose</b>: Define the interface and common protocol of a TopLink compliant session.
50  * <p>
51  * <b>Description</b>: The session is the primary interface into TopLink,
52  * the application should do all of its reading and writing of objects through the session.
53  * The session also manages transactions and units of work. Normally the session
54  * is passed and used by the application controler objects. Controler objects normally
55  * sit behind the GUI and perform the buiness processes required for the application,
56  * they should perform all explict database access and database access should be avoided from
57  * the domain object model. Do not use a globally accessable session instance, doing so does
58  * not allow for multiple sessions. Multiple sessions may required when performing things like
59  * data migration or multiple database access, as well the unit of work feature requires the usage
60  * of multiple session instances. Although session is abstract, any users of its subclasses
61  * should only cast the variables to Session to allow usage of any of its subclasses.
62  * <p>
63  * <b>Responsibilities</b>:
64  * <ul>
65  * <li> Connecting/disconnecting.
66  * <li> Reading and writing objects.
67  * <li> Transaction and unit of work support.
68  * <li> Identity maps and caching.
69  * </ul>
70  * @see DatabaseSession
71  */

72 public abstract class AbstractSession implements oracle.toplink.essentials.sessions.Session, java.io.Serializable JavaDoc, java.lang.Cloneable JavaDoc {
73
74     /** ExceptionHandler handles database exceptions. */
75     transient protected ExceptionHandler exceptionHandler;
76
77     /** IntegrityChecker catch all the descriptor Exceptions. */
78     transient protected IntegrityChecker integrityChecker;
79
80     /** The project stores configuration information, such as the descriptors and login. */
81     transient protected oracle.toplink.essentials.sessions.Project project;
82
83     /** Ensure mutual exclusion of the session's transaction state across multiple threads.*/
84     transient protected ConcurrencyManager transactionMutex;
85
86     /** Manages the live object cache.*/
87     protected oracle.toplink.essentials.internal.sessions.IdentityMapAccessor identityMapAccessor;
88
89     /** If Transactions were externally started */
90     protected boolean wasJTSTransactionInternallyStarted;
91
92     /** The connection to the data store. */
93     transient protected Accessor accessor;
94     
95     /** Allow the datasource platform to be cached. */
96     transient protected Platform platform;
97
98     /** Stores predefine reusable queries.*/
99     transient protected Map queries;
100     
101     /** Stores predefined not yet parsed EJBQL queries.*/
102     transient protected List ejbqlPlaceHolderQueries;
103
104     /** Resolves referencial integrity on commits. */
105     transient protected CommitManager commitManager;
106
107     /** Tool that log performance information. */
108     transient protected SessionProfiler profiler;
109
110     /** Support being owned by a session broker. */
111     transient protected AbstractSession broker;
112
113     /** Used to identify a session when using the session broker. */
114     protected String JavaDoc name;
115
116     /** Keep track of active units of work. */
117     transient protected int numberOfActiveUnitsOfWork;
118
119     /** Destination for logged messages and SQL. */
120     transient protected SessionLog sessionLog;
121
122     /** When logging the name of the session is typed: class name + system hashcode. */
123     transient protected String JavaDoc logSessionString;
124
125     /** Stores the event listeners for this session. */
126     transient protected SessionEventManager eventManager;
127
128     /** Allow for user defined properties. */
129     protected Map properties;
130
131     /** Delegate that handles synchronizing a UnitOfWork with an external transaction. */
132     transient protected ExternalTransactionController externalTransactionController;
133
134     /** Last descriptor accessed, use to optimize descriptor lookup. */
135     transient protected ClassDescriptor lastDescriptorAccessed;
136
137     /** Used to determine If a session is in a profile or not */
138     public boolean isInProfile;
139
140     /**
141      * INTERNAL:
142      * Create and return a new session.
143      * This should only be called if the database login information is not know at the time of creation.
144      * Normally it is better to call the constructor that takes the login information as an argument
145      * so that the session can initialize itself to the platform information given in the login.
146      */

147     protected AbstractSession() {
148         this.name = "";
149         initializeIdentityMapAccessor();
150         // PERF - move to lazy init (3286091)
151
this.numberOfActiveUnitsOfWork = 0;
152     }
153
154     /**
155      * INTERNAL:
156      * Create a blank session, used for proxy session.
157      */

158     protected AbstractSession(int nothing) {
159     }
160
161     /**
162      * PUBLIC:
163      * Create and return a new session.
164      * By giving the login information on creation this allows the session to initialize itself
165      * to the platform given in the login. This constructor does not return a connected session.
166      * To connect the session to the database login() must be sent to it. The login(userName, password)
167      * method may also be used to connect the session, this allows for the user name and password
168      * to be given at login but for the other database information to be provided when the session is created.
169      */

170     public AbstractSession(Login login) {
171         this(new oracle.toplink.essentials.sessions.Project(login));
172     }
173
174     /**
175      * PUBLIC:
176      * Create and return a new session.
177      * This constructor does not return a connected session.
178      * To connect the session to the database login() must be sent to it. The login(userName, password)
179      * method may also be used to connect the session, this allows for the user name and password
180      * to be given at login but for the other database information to be provided when the session is created.
181      */

182     public AbstractSession(oracle.toplink.essentials.sessions.Project project) {
183         this();
184         this.project = project;
185         if (project.getDatasourceLogin() == null) {
186             throw ValidationException.projectLoginIsNull(this);
187         }
188     }
189
190     /**
191      * INTERNAL:
192      * Called by a sessions queries to obtain individual query ids.
193      * CR #2698903
194      */

195     public long getNextQueryId() {
196         return QueryCounter.getCount();
197     }
198
199     /**
200      * INTERNAL:
201      * Return a unit of work for this session not registered with the JTS transaction.
202      */

203     public UnitOfWorkImpl acquireNonSynchronizedUnitOfWork() {
204         setNumberOfActiveUnitsOfWork(getNumberOfActiveUnitsOfWork() + 1);
205         UnitOfWorkImpl unitOfWork = new UnitOfWorkImpl(this);
206         if (shouldLog(SessionLog.FINER, SessionLog.TRANSACTION)) {
207             log(SessionLog.FINER, SessionLog.TRANSACTION, "acquire_unit_of_work_with_argument", String.valueOf(System.identityHashCode(unitOfWork)));
208         }
209         return unitOfWork;
210     }
211
212     /**
213      * PUBLIC:
214      * Return a unit of work for this session.
215      * The unit of work is an object level transaction that allows
216      * a group of changes to be applied as a unit.
217      *
218      * @see UnitOfWork
219      */

220     public UnitOfWork acquireUnitOfWork() {
221         UnitOfWorkImpl unitOfWork = acquireNonSynchronizedUnitOfWork();
222         unitOfWork.registerWithTransactionIfRequired();
223
224         return unitOfWork;
225     }
226
227     /**
228      * PUBLIC:
229      * Add an alias for the descriptor
230      */

231     public void addAlias(String JavaDoc alias, ClassDescriptor descriptor) {
232         project.addAlias(alias, descriptor);
233     }
234
235     /**
236      * PUBLIC:
237      * Add the query to the session queries with the given name.
238      * This allows for common queries to be pre-defined, reused and executed by name.
239      */

240     public void addQuery(String JavaDoc name, DatabaseQuery query) {
241         query.setName(name);
242         addQuery(query);
243     }
244
245     /**
246      * INTERNAL:
247      * Return all pre-defined not yet parsed EJBQL queries.
248      * @see #getAllQueries()
249      */

250     public void addEjbqlPlaceHolderQuery(DatabaseQuery query) {
251         getEjbqlPlaceHolderQueries().add(query);
252     }
253
254     /**
255      * INTERNAL:
256      * Add the query to the session queries.
257      */

258     protected void addQuery(DatabaseQuery query) {
259         Vector queriesByName = (Vector)getQueries().get(query.getName());
260         if (queriesByName == null) {
261             // lazily create Vector in Hashtable.
262
queriesByName = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance();
263             getQueries().put(query.getName(), queriesByName);
264         }
265
266         // Check that we do not already have a query that matched it
267
for (Enumeration enumtr = queriesByName.elements(); enumtr.hasMoreElements();) {
268             DatabaseQuery existingQuery = (DatabaseQuery)enumtr.nextElement();
269             if (Helper.areTypesAssignable(query.getArgumentTypes(), existingQuery.getArgumentTypes())) {
270                 throw ValidationException.existingQueryTypeConflict(query, existingQuery);
271             }
272         }
273         queriesByName.add(query);
274     }
275
276     /**
277      * INTERNAL:
278      * Called by beginTransaction() to start a transaction.
279      * This starts a real database transaction.
280      */

281     protected void basicBeginTransaction() throws DatabaseException {
282         try {
283             getAccessor().beginTransaction(this);
284         } catch (RuntimeException JavaDoc exception) {
285             handleException(exception);
286         }
287     }
288
289     /**
290      * INTERNAL:
291      * Called after transaction is completed (committed or rolled back)
292      */

293     public void afterTransaction(boolean committed, boolean isExternalTransaction) {
294     }
295
296     /**
297      * INTERNAL:
298      * Called by commitTransaction() to commit a transaction.
299      * This commits the active transaction.
300      */

301     protected void basicCommitTransaction() throws DatabaseException {
302         try {
303             getAccessor().commitTransaction(this);
304         } catch (RuntimeException JavaDoc exception) {
305             handleException(exception);
306         }
307     }
308
309     /**
310      * INTERNAL:
311      * Called by rollbackTransaction() to rollback a transaction.
312      * This rollsback the active transaction.
313      */

314     protected void basicRollbackTransaction() throws DatabaseException {
315         try {
316             getAccessor().rollbackTransaction(this);
317         } catch (RuntimeException JavaDoc exception) {
318             handleException(exception);
319         }
320     }
321
322     /**
323      * INTERNAL:
324      * Attempts to begin an external transaction.
325      * Returns true only in one case -
326      * extenal transaction has been internally started during this method call:
327      * wasJTSTransactionInternallyStarted()==false in the beginning of this method and
328      * wasJTSTransactionInternallyStarted()==true in the end of this method.
329      */

330     public boolean beginExternalTransaction() {
331         boolean externalTransactionHasBegun = false;
332         if (hasExternalTransactionController() && !wasJTSTransactionInternallyStarted()) {
333             try {
334                 getExternalTransactionController().beginTransaction(this);
335             } catch (RuntimeException JavaDoc exception) {
336                 handleException(exception);
337             }
338             if (wasJTSTransactionInternallyStarted()) {
339                 externalTransactionHasBegun = true;
340                 log(SessionLog.FINER, SessionLog.TRANSACTION, "external_transaction_has_begun_internally");
341             }
342         }
343         return externalTransactionHasBegun;
344     }
345
346     /**
347      * PUBLIC:
348      * Begin a transaction on the database.
349      * This allows a group of database modification to be commited or rolledback as a unit.
350      * All writes/deletes will be sent to the database be will not be visible to other users until commit.
351      * Although databases do not allow nested transaction,
352      * TopLink supports nesting through only committing to the database on the outer commit.
353      *
354      * @exception DatabaseException if the database connection is lost or the begin is rejected.
355      * @exception ConcurrencyException if this session's transaction is aquired by another thread and a timeout occurs.
356      *
357      * @see #isInTransaction()
358      */

359     public void beginTransaction() throws DatabaseException, ConcurrencyException {
360         // If there is no db transaction in progress
361
// beginExternalTransaction() starts an external transaction -
362
// provided externalTransactionController is used, and there is
363
// no active external transaction - so we have to start one internally.
364
if (!isInTransaction()) {
365             beginExternalTransaction();
366         }
367
368         // For unit of work and client session multi threading is allowed as they are a context,
369
// this is required for JTS/RMI/CORBA/EJB stuff where the server thread can be different across calls.
370
if (isUnitOfWork() || isClientSession()) {
371             getTransactionMutex().setActiveThread(Thread.currentThread());
372         }
373
374         // Ensure mutual exclusion and call subclass specific begin.
375
getTransactionMutex().acquire();
376         if (!getTransactionMutex().isNested()) {
377             getEventManager().preBeginTransaction();
378             basicBeginTransaction();
379             getEventManager().postBeginTransaction();
380         }
381     }
382
383     /**
384      * PUBLIC:
385      * clear the integrityChecker. IntegrityChecker holds all the Descriptor Exceptions.
386      */

387     public void clearIntegrityChecker() {
388         setIntegrityChecker(null);
389     }
390
391     /**
392      * INTERNAL:
393      * clear the lastDescriptorAccessed.
394      */

395     public void clearLastDescriptorAccessed() {
396         lastDescriptorAccessed = null;
397     }
398
399     /**
400      * PUBLIC:
401      * Clear the profiler, this will end the current profile opperation.
402      */

403     public void clearProfile() {
404         setProfiler(null);
405     }
406
407     /**
408      * INTERNAL:
409      * Clones the descriptor
410      */

411     public Object JavaDoc clone() {
412         // An alternative to this process should be found
413
try {
414             return super.clone();
415         } catch (Exception JavaDoc exception) {
416             return null;
417         }
418     }
419
420     /**
421      * INTERNAL:
422      * Attempts to commit the running internally started external transaction.
423      * Returns true only in one case -
424      * extenal transaction has been internally committed during this method call:
425      * wasJTSTransactionInternallyStarted()==true in the beginning of this method and
426      * wasJTSTransactionInternallyStarted()==false in the end of this method.
427      */

428     public boolean commitExternalTransaction() {
429         boolean externalTransactionHasCommitted = false;
430         if (hasExternalTransactionController() && wasJTSTransactionInternallyStarted()) {
431             try {
432                 getExternalTransactionController().commitTransaction(this);
433             } catch (RuntimeException JavaDoc exception) {
434                 handleException(exception);
435             }
436             if (!wasJTSTransactionInternallyStarted()) {
437                 externalTransactionHasCommitted = true;
438                 log(SessionLog.FINER, SessionLog.TRANSACTION, "external_transaction_has_committed_internally");
439             }
440         }
441         return externalTransactionHasCommitted;
442     }
443
444     /**
445      * PUBLIC:
446      * Commit the active database transaction.
447      * This allows a group of database modification to be commited or rolledback as a unit.
448      * All writes/deletes will be sent to the database be will not be visible to other users until commit.
449      * Although databases do not allow nested transaction,
450      * TopLink supports nesting through only committing to the database on the outer commit.
451      *
452      * @exception DatabaseException most databases validate changes as they are done,
453      * normally errors do not occur on commit unless the disk fails or the connection is lost.
454      * @exception ConcurrencyException if this session is not within a transaction.
455      */

456     public void commitTransaction() throws DatabaseException, ConcurrencyException {
457         // Release mutex and call subclass specific commit.
458
if (!getTransactionMutex().isNested()) {
459             getEventManager().preCommitTransaction();
460             basicCommitTransaction();
461             getEventManager().postCommitTransaction();
462         }
463
464         // This MUST not be in a try catch or finally as if the commit failed the transaction is still open.
465
getTransactionMutex().release();
466
467         // If there is no db transaction in progress
468
// if there is an active external transaction
469
// which was started internally - it should be committed internally, too.
470
if (!isInTransaction()) {
471             commitExternalTransaction();
472         }
473     }
474
475     /**
476      * INTERNAL:
477      * Return if the two object match completely.
478      * This checks the objects attributes and their private parts.
479      */

480     public boolean compareObjects(Object JavaDoc firstObject, Object JavaDoc secondObject) {
481         if ((firstObject == null) && (secondObject == null)) {
482             return true;
483         }
484
485         if ((firstObject == null) || (secondObject == null)) {
486             return false;
487         }
488
489         if (!(firstObject.getClass().equals(secondObject.getClass()))) {
490             return false;
491         }
492
493         ObjectBuilder builder = getDescriptor(firstObject.getClass()).getObjectBuilder();
494
495         return builder.compareObjects(builder.unwrapObject(firstObject, this), builder.unwrapObject(secondObject, this), this);
496     }
497
498     /**
499      * TESTING:
500      * Return true if the object do not match.
501      * This checks the objects attributes and their private parts.
502      */

503     public boolean compareObjectsDontMatch(Object JavaDoc firstObject, Object JavaDoc secondObject) {
504         return !this.compareObjects(firstObject, secondObject);
505     }
506
507     /**
508      * PUBLIC:
509      * Return true if the pre-defined query is defined on the session.
510      */

511     public boolean containsQuery(String JavaDoc queryName) {
512         return getQueries().containsKey(queryName);
513     }
514
515     /**
516      * PUBLIC:
517      * Return a complete copy of the object.
518      * This can be used to obtain a scatch copy of an object,
519      * or for templatizing an existing object into another new object.
520      * The object and all of its privately owned parts will be copied, the object's primary key will be reset to null.
521      *
522      * @see #copyObject(Object, ObjectCopyingPolicy)
523      */

524     public Object JavaDoc copyObject(Object JavaDoc original) {
525         return copyObject(original, new ObjectCopyingPolicy());
526     }
527
528     /**
529      * PUBLIC:
530      * Return a complete copy of the object.
531      * This can be used to obtain a scatch copy of an object,
532      * or for templatizing an existing object into another new object.
533      * The object copying policy allow for the depth, and reseting of the primary key to null, to be specified.
534      */

535     public Object JavaDoc copyObject(Object JavaDoc original, ObjectCopyingPolicy policy) {
536         if (original == null) {
537             return null;
538         }
539
540         ClassDescriptor descriptor = getDescriptor(original);
541         if (descriptor == null) {
542             return original;
543         }
544
545         policy.setSession(this);
546         return descriptor.getObjectBuilder().copyObject(original, policy);
547     }
548
549     /**
550      * INTERNAL:
551      * Copy the read only classes from the unit of work
552      *
553      * Added Nov 8, 2000 JED for Patch 2.5.1.8
554      * Ref: Prs 24502
555      */

556     public Vector copyReadOnlyClasses() {
557         return getDefaultReadOnlyClasses();
558     }
559
560     /**
561      * PUBLIC:
562      * delete all of the objects and all of their privately owned parts in the database.
563      * The allows for a group of objects to be deleted as a unit.
564      * The objects will be deleted through a single transactions.
565      *
566      * @exception DatabaseException if an error occurs on the database,
567      * these include constraint violations, security violations and general database erros.
568      * @exception OptimisticLockException if the object's descriptor is using optimistic locking and
569      * the object has been updated or deleted by another user since it was last read.
570      */

571     public void deleteAllObjects(Collection domainObjects) throws DatabaseException, OptimisticLockException {
572         for (Iterator objectsEnum = domainObjects.iterator(); objectsEnum.hasNext();) {
573             deleteObject(objectsEnum.next());
574         }
575     }
576
577     /**
578      * PUBLIC:
579      * delete all of the objects and all of their privately owned parts in the database.
580      * The allows for a group of objects to be deleted as a unit.
581      * The objects will be deleted through a single transactions.
582      *
583      * @exception DatabaseException if an error occurs on the database,
584      * these include constraint violations, security violations and general database erros.
585      * @exception OptimisticLockException if the object's descriptor is using optimistic locking and
586      * the object has been updated or deleted by another user since it was last read.
587      */

588     public void deleteAllObjects(Vector domainObjects) throws DatabaseException, OptimisticLockException {
589         for (Enumeration objectsEnum = domainObjects.elements(); objectsEnum.hasMoreElements();) {
590             deleteObject(objectsEnum.nextElement());
591         }
592     }
593
594     /**
595      * PUBLIC:
596      * Delete the object and all of its privately owned parts from the database.
597      * The delete operation can be customized through using a delete query.
598      *
599      * @exception DatabaseException if an error occurs on the database,
600      * these include constraint violations, security violations and general database erros.
601      * An database error is not raised if the object is already deleted or no rows are effected.
602      * @exception OptimisticLockException if the object's descriptor is using optimistic locking and
603      * the object has been updated or deleted by another user since it was last read.
604      *
605      * @see DeleteObjectQuery
606      */

607     public Object JavaDoc deleteObject(Object JavaDoc domainObject) throws DatabaseException, OptimisticLockException {
608         DeleteObjectQuery query = new DeleteObjectQuery();
609         query.setObject(domainObject);
610         return executeQuery(query);
611     }
612
613     /**
614      * PUBLIC:
615      * Return if the object exists on the database or not.
616      * This always checks existence on the database.
617      */

618     public boolean doesObjectExist(Object JavaDoc object) throws DatabaseException {
619         DoesExistQuery query = new DoesExistQuery();
620         query.setObject(object);
621         query.checkDatabaseForDoesExist();
622         return ((Boolean JavaDoc)executeQuery(query)).booleanValue();
623     }
624
625     /**
626      * PUBLIC:
627      * Turn off logging
628      */

629     public void dontLogMessages() {
630         setLogLevel(SessionLog.OFF);
631     }
632
633     /**
634      * INTERNAL:
635      * End the operation timing.
636      */

637     public void endOperationProfile(String JavaDoc operationName) {
638         if (isInProfile()) {
639             getProfiler().endOperationProfile(operationName);
640         }
641     }
642
643     /**
644      * INTERNAL:
645      * Updates the value of SessionProfiler state
646      */

647     public void updateProfile(String JavaDoc operationName, Object JavaDoc value) {
648         if (isInProfile()) {
649             getProfiler().update(operationName, value);
650         }
651     }
652
653     /**
654      * INTERNAL:
655      * Updates the count of SessionProfiler event
656      */

657     public void incrementProfile(String JavaDoc operationName) {
658         if (isInProfile()) {
659             getProfiler().occurred(operationName);
660         }
661     }
662
663     /**
664      * INTERNAL:
665      * Overridden by subclasses that do more than just execute the call.
666      * Executes the call directly on this session and does not check which
667      * session it should have executed on.
668      */

669     public Object JavaDoc executeCall(Call call, AbstractRecord translationRow, DatabaseQuery query) throws DatabaseException {
670         //** sequencing refactoring
671
if (query.getAccessor() == null) {
672             query.setAccessor(getAccessor());
673         }
674         try {
675             return query.getAccessor().executeCall(call, translationRow, this);
676         } finally {
677             if (call.isFinished()) {
678                 query.setAccessor(null);
679             }
680         }
681     }
682
683     /**
684      * PUBLIC:
685      * Execute the call on the database.
686      * The row count is returned.
687      * The call can be a stored procedure call, SQL call or other type of call.
688      * <p>Example:
689      * <p>session.executeNonSelectingCall(new SQLCall("Delete from Employee");
690      *
691      * @see #executeSelectingCall(Call)
692      */

693     public int executeNonSelectingCall(Call call) throws DatabaseException {
694         DataModifyQuery query = new DataModifyQuery();
695         query.setCall(call);
696         Integer JavaDoc value = (Integer JavaDoc)executeQuery(query);
697         if (value == null) {
698             return 0;
699         } else {
700             return value.intValue();
701         }
702     }
703
704     /**
705      * PUBLIC:
706      * Execute the sql on the database.
707      * <p>Example:
708      * <p>session.executeNonSelectingSQL("Delete from Employee");
709      * @see #executeNonSelectingCall(Call)
710      */

711     public void executeNonSelectingSQL(String JavaDoc sqlString) throws DatabaseException {
712         executeNonSelectingCall(new SQLCall(sqlString));
713     }
714
715     /**
716      * PUBLIC:
717      * Execute the pre-defined query by name and return the result.
718      * Queries can be pre-defined and named to allow for their reuse.
719      *
720      * @see #addQuery(String, DatabaseQuery)
721      */

722     public Object JavaDoc executeQuery(String JavaDoc queryName) throws DatabaseException {
723         DatabaseQuery query = getQuery(queryName);
724
725         if (query == null) {
726             throw QueryException.queryNotDefined(queryName);
727         }
728
729         return executeQuery(query);
730     }
731
732     /**
733      * PUBLIC:
734      * Execute the pre-defined query by name and return the result.
735      * Queries can be pre-defined and named to allow for their reuse.
736      * The class is the descriptor in which the query was pre-defined.
737      *
738      * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
739      */

740     public Object JavaDoc executeQuery(String JavaDoc queryName, Class JavaDoc domainClass) throws DatabaseException {
741         ClassDescriptor descriptor = getDescriptor(domainClass);
742
743         if (descriptor == null) {
744             throw QueryException.descriptorIsMissingForNamedQuery(domainClass, queryName);
745         }
746
747         DatabaseQuery query = (DatabaseQuery)descriptor.getQueryManager().getQuery(queryName);
748
749         if (query == null) {
750             throw QueryException.queryNotDefined(queryName, domainClass);
751         }
752
753         return executeQuery(query);
754     }
755
756     /**
757      * PUBLIC:
758      * Execute the pre-defined query by name and return the result.
759      * Queries can be pre-defined and named to allow for their reuse.
760      * The class is the descriptor in which the query was pre-defined.
761      *
762      * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
763      */

764     public Object JavaDoc executeQuery(String JavaDoc queryName, Class JavaDoc domainClass, Object JavaDoc arg1) throws DatabaseException {
765         Vector argumentValues = new Vector();
766         argumentValues.addElement(arg1);
767         return executeQuery(queryName, domainClass, argumentValues);
768     }
769
770     /**
771      * PUBLIC:
772      * Execute the pre-defined query by name and return the result.
773      * Queries can be pre-defined and named to allow for their reuse.
774      * The class is the descriptor in which the query was pre-defined.
775      *
776      * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
777      */

778     public Object JavaDoc executeQuery(String JavaDoc queryName, Class JavaDoc domainClass, Object JavaDoc arg1, Object JavaDoc arg2) throws DatabaseException {
779         Vector argumentValues = new Vector();
780         argumentValues.addElement(arg1);
781         argumentValues.addElement(arg2);
782         return executeQuery(queryName, domainClass, argumentValues);
783     }
784
785     /**
786      * PUBLIC:
787      * Execute the pre-defined query by name and return the result.
788      * Queries can be pre-defined and named to allow for their reuse.
789      * The class is the descriptor in which the query was pre-defined.
790      *
791      * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
792      */

793     public Object JavaDoc executeQuery(String JavaDoc queryName, Class JavaDoc domainClass, Object JavaDoc arg1, Object JavaDoc arg2, Object JavaDoc arg3) throws DatabaseException {
794         Vector argumentValues = new Vector();
795         argumentValues.addElement(arg1);
796         argumentValues.addElement(arg2);
797         argumentValues.addElement(arg3);
798         return executeQuery(queryName, domainClass, argumentValues);
799     }
800
801     /**
802      * PUBLIC:
803      * Execute the pre-defined query by name and return the result.
804      * Queries can be pre-defined and named to allow for their reuse.
805      * The class is the descriptor in which the query was pre-defined.
806      *
807      * @see DescriptorQueryManager#addQuery(String, DatabaseQuery)
808      */

809     public Object JavaDoc executeQuery(String JavaDoc queryName, Class JavaDoc domainClass, Vector argumentValues) throws DatabaseException {
810         ClassDescriptor descriptor = getDescriptor(domainClass);
811
812         if (descriptor == null) {
813             throw QueryException.descriptorIsMissingForNamedQuery(domainClass, queryName);
814         }
815
816         DatabaseQuery query = (DatabaseQuery)descriptor.getQueryManager().getQuery(queryName, argumentValues);
817
818         if (query == null) {
819             throw QueryException.queryNotDefined(queryName, domainClass);
820         }
821
822         return executeQuery(query, argumentValues);
823     }
824
825     /**
826      * PUBLIC:
827      * Execute the pre-defined query by name and return the result.
828      * Queries can be pre-defined and named to allow for their reuse.
829      *
830      * @see #addQuery(String, DatabaseQuery)
831      */

832     public Object JavaDoc executeQuery(String JavaDoc queryName, Object JavaDoc arg1) throws DatabaseException {
833         Vector argumentValues = new Vector();
834         argumentValues.addElement(arg1);
835         return executeQuery(queryName, argumentValues);
836     }
837
838     /**
839      * PUBLIC:
840      * Execute the pre-defined query by name and return the result.
841      * Queries can be pre-defined and named to allow for their reuse.
842      *
843      * @see #addQuery(String, DatabaseQuery)
844      */

845     public Object JavaDoc executeQuery(String JavaDoc queryName, Object JavaDoc arg1, Object JavaDoc arg2) throws DatabaseException {
846         Vector argumentValues = new Vector();
847         argumentValues.addElement(arg1);
848         argumentValues.addElement(arg2);
849         return executeQuery(queryName, argumentValues);
850     }
851
852     /**
853      * PUBLIC:
854      * Execute the pre-defined query by name and return the result.
855      * Queries can be pre-defined and named to allow for their reuse.
856      *
857      * @see #addQuery(String, DatabaseQuery)
858      */

859     public Object JavaDoc executeQuery(String JavaDoc queryName, Object JavaDoc arg1, Object JavaDoc arg2, Object JavaDoc arg3) throws DatabaseException {
860         Vector argumentValues = new Vector();
861         argumentValues.addElement(arg1);
862         argumentValues.addElement(arg2);
863         argumentValues.addElement(arg3);
864         return executeQuery(queryName, argumentValues);
865     }
866
867     /**
868      * PUBLIC:
869      * Execute the pre-defined query by name and return the result.
870      * Queries can be pre-defined and named to allow for their reuse.
871      *
872      * @see #addQuery(String, DatabaseQuery)
873      */

874     public Object JavaDoc executeQuery(String JavaDoc queryName, Vector argumentValues) throws DatabaseException {
875         DatabaseQuery query = getQuery(queryName, argumentValues);
876
877         if (query == null) {
878             throw QueryException.queryNotDefined(queryName);
879         }
880
881         return executeQuery(query, argumentValues);
882     }
883
884     /**
885      * PUBLIC:
886      * Execute the database query.
887      * A query is a database operation such as reading or writting.
888      * The query allows for the operation to be customized for such things as,
889      * performance, depth, caching, etc.
890      *
891      * @see DatabaseQuery
892      */

893     public Object JavaDoc executeQuery(DatabaseQuery query) throws DatabaseException {
894         return executeQuery(query, new DatabaseRecord(1));
895     }
896
897     /**
898      * PUBLIC:
899      * Return the results from exeucting the database query.
900      * the arguments are passed in as a vector
901      */

902     public Object JavaDoc executeQuery(DatabaseQuery query, Vector argumentValues) throws DatabaseException {
903         if (query == null) {
904             throw QueryException.queryNotDefined();
905         }
906
907         AbstractRecord row = query.rowFromArguments(argumentValues);
908
909         return executeQuery(query, row);
910     }
911
912     /**
913      * INTERNAL:
914      * Return the results from exeucting the database query.
915      * the arguments should be a database row with raw data values.
916      */

917     public Object JavaDoc executeQuery(DatabaseQuery query, AbstractRecord row) throws DatabaseException {
918         if (hasBroker()) {
919             if (!((query.isDataModifyQuery() || query.isDataReadQuery()) && (query.getSessionName() == null))) {
920                 return getBroker().executeQuery(query, row);
921             }
922         }
923
924         if (query == null) {
925             throw QueryException.queryNotDefined();
926         }
927
928         //CR#2272
929
log(SessionLog.FINEST, SessionLog.QUERY, "execute_query", query);
930
931         try {
932             getEventManager().preExecuteQuery(query);
933             Object JavaDoc result;
934             if (isInProfile()) {
935                 result = getProfiler().profileExecutionOfQuery(query, row, this);
936             } else {
937                 result = internalExecuteQuery(query, row);
938             }
939             getEventManager().postExecuteQuery(query, result);
940             return result;
941         } catch (RuntimeException JavaDoc exception) {
942             if (exception instanceof QueryException) {
943                 QueryException queryException = (QueryException)exception;
944                 if (queryException.getQuery() == null) {
945                     queryException.setQuery(query);
946                 }
947                 if (queryException.getQueryArgumentsRecord() == null) {
948                     queryException.setQueryArguments(row);
949                 }
950                 if (queryException.getSession() == null) {
951                     queryException.setSession(this);
952                 }
953             } else if (exception instanceof DatabaseException) {
954                 DatabaseException databaseException = (DatabaseException)exception;
955                 if (databaseException.getQuery() == null) {
956                     databaseException.setQuery(query);
957                 }
958                 if (databaseException.getQueryArgumentsRecord() == null) {
959                     databaseException.setQueryArguments(row);
960                 }
961                 if (databaseException.getSession() == null) {
962                     databaseException.setSession(this);
963                 }
964             }
965             return handleException(exception);
966         }
967     }
968
969     /**
970      * PUBLIC:
971      * Execute the call on the database and return the result.
972      * The call must return a value, if no value is return executeNonSelectCall must be used.
973      * The call can be a stored procedure call, SQL call or other type of call.
974      * A vector of database rows is returned, database row implements Java 2 Map which should be used to access the data.
975      * <p>Example:
976      * <p>session.executeSelectingCall(new SQLCall("Select * from Employee");
977      *
978      * @see #executeNonSelectingCall(Call)
979      */

980     public Vector executeSelectingCall(Call call) throws DatabaseException {
981         DataReadQuery query = new DataReadQuery();
982         query.setCall(call);
983         return (Vector)executeQuery(query);
984     }
985
986     /**
987      * PUBLIC:
988      * Execute the sql on the database and return the result.
989      * It must return a value, if no value is return executeNonSelectingSQL must be used.
990      * A vector of database rows is returned, database row implements Java 2 Map which should be used to access the data.
991      * <p>Example:
992      * <p>session.executeSelectingCall("Select * from Employee");
993      *
994      * @see #executeSelectingCall(Call)
995      */

996     public Vector executeSQL(String JavaDoc sqlString) throws DatabaseException {
997         return executeSelectingCall(new SQLCall(sqlString));
998     }
999
1000    /**
1001     * INTERNAL:
1002     * Return the lowlevel database accessor.
1003     * The database accesor is used for direct database access.
1004     */

1005    public synchronized Accessor getAccessor() {
1006        if ((accessor == null) && (project != null) && (project.getDatasourceLogin() != null)) {
1007            // PERF: lazy init, not always required.
1008
accessor = project.getDatasourceLogin().buildAccessor();
1009        }
1010        return accessor;
1011    }
1012
1013    /**
1014     * INTERNAL:
1015     * Return the lowlevel database accessor.
1016     * The database accesor is used for direct database access.
1017     * If sessionBroker is used, the right accessor for this
1018     * broker will be returned.
1019     */

1020    public Accessor getAccessor(Class JavaDoc domainClass) {
1021        return getAccessor();
1022    }
1023
1024    /**
1025     * INTERNAL:
1026     * Return the lowlevel database accessor.
1027     * The database accesor is used for direct database access.
1028     * If sessionBroker is used, the right accessor for this
1029     * broker will be returned based on the session name.
1030     */

1031    public Accessor getAccessor(String JavaDoc sessionName) {
1032        return getAccessor();
1033    }
1034
1035    /**
1036     * PUBLIC:
1037     * Return the active session for the current active external (JTS) transaction.
1038     * This should only be used with JTS and will return the session if no external transaction exists.
1039     */

1040    public oracle.toplink.essentials.sessions.Session getActiveSession() {
1041        oracle.toplink.essentials.sessions.Session activeSession = getActiveUnitOfWork();
1042        if (activeSession == null) {
1043            activeSession = this;
1044        }
1045
1046        return activeSession;
1047    }
1048
1049    /**
1050     * PUBLIC:
1051     * Return the active unit of work for the current active external (JTS) transaction.
1052     * This should only be used with JTS and will return null if no external transaction exists.
1053     */

1054    public oracle.toplink.essentials.sessions.UnitOfWork getActiveUnitOfWork() {
1055        if (hasExternalTransactionController()) {
1056            return getExternalTransactionController().getActiveUnitOfWork();
1057        }
1058
1059        /* Steven Vo: CR# 2517
1060           Get from the server session since the external transaction controller could be
1061           null out from the client session by TL WebLogic 5.1 to provide non-jts transaction
1062           operations
1063          */

1064        if (isClientSession()) {
1065            return ((oracle.toplink.essentials.threetier.ClientSession)this).getParent().getActiveUnitOfWork();
1066        }
1067
1068        return null;
1069    }
1070
1071    /**
1072     * INTERNAL:
1073     * Returns the alias descriptors hashtable.
1074     */

1075    public Map getAliasDescriptors() {
1076        return project.getAliasDescriptors();
1077    }
1078
1079    /**
1080     * INTERNAL:
1081     * Allow the session to be used from a session broker.
1082     */

1083    public AbstractSession getBroker() {
1084        return broker;
1085    }
1086
1087    /**
1088     * INTERNAL:
1089     * The session that this query is executed against when not in transaction.
1090     * The session containing the shared identity map.
1091     * <p>
1092     * In most cases this is the root ServerSession or DatabaseSession.
1093     * <p>
1094     * In cases where objects are not to be cached in the global identity map
1095     * an alternate session may be returned:
1096     * <ul>
1097     * <li>A ClientSession if in transaction
1098     * <li>An isolated ClientSession or HistoricalSession
1099     * <li>A registered session of a root SessionBroker
1100     * </ul>
1101     */

1102    public AbstractSession getRootSession(DatabaseQuery query) {
1103        return getParentIdentityMapSession(query, false, true);
1104    }
1105
1106    /**
1107     * INTERNAL:
1108     * Gets the next link in the chain of sessions followed by a query's check
1109     * early return, the chain of sessions with identity maps all the way up to
1110     * the root session.
1111     */

1112    public AbstractSession getParentIdentityMapSession(DatabaseQuery query) {
1113        return getParentIdentityMapSession(query, false, false);
1114    }
1115
1116    /**
1117     * INTERNAL:
1118     * Gets the next link in the chain of sessions followed by a query's check
1119     * early return, the chain of sessions with identity maps all the way up to
1120     * the root session.
1121     * <p>
1122     * Used for session broker which delegates to registered sessions, or UnitOfWork
1123     * which checks parent identity map also.
1124     * @param canReturnSelf true when method calls itself. If the path
1125     * starting at <code>this</code> is acceptable. Sometimes true if want to
1126     * move to the first valid session, i.e. executing on ClientSession when really
1127     * should be on ServerSession.
1128     * @param terminalOnly return the session we will execute the call on, not
1129     * the next step towards it.
1130     * @return this if there is no next link in the chain
1131     */

1132    public AbstractSession getParentIdentityMapSession(DatabaseQuery query, boolean canReturnSelf, boolean terminalOnly) {
1133        return this;
1134    }
1135
1136    /**
1137     * INTERNAL:
1138     * Gets the session which this query will be executed on.
1139     * Generally will be called immediately before the call is translated,
1140     * which is immediately before session.executeCall.
1141     * <p>
1142     * Since the execution session also knows the correct datasource platform
1143     * to execute on, it is often used in the mappings where the platform is
1144     * needed for type conversion, or where calls are translated.
1145     * <p>
1146     * Is also the session with the accessor. Will return a ClientSession if
1147     * it is in transaction and has a write connection.
1148     * @return a session with a live accessor
1149     * @param query may store session name or reference class for brokers case
1150     */

1151    public AbstractSession getExecutionSession(DatabaseQuery query) {
1152        return this;
1153    }
1154
1155    /**
1156     * INTERNAL:
1157     * The commit manager is used to resolve referncial integrity on commits of multiple objects.
1158     * All brokered sessions share the same commit manager.
1159     */

1160    public CommitManager getCommitManager() {
1161        if (hasBroker()) {
1162            return getBroker().getCommitManager();
1163        }
1164
1165        // PERF: lazy init, not always required, not required for client sessions
1166
if (commitManager == null) {
1167            commitManager = new CommitManager(this);
1168        }
1169        return commitManager;
1170    }
1171
1172    /**
1173     * INTERNAL:
1174     * Returns the set of read-only classes that gets assigned to each newly created UnitOfWork.
1175     *
1176     * @see oracle.toplink.essentials.sessions.Project#setDefaultReadOnlyClasses(Vector)
1177     */

1178    public Vector getDefaultReadOnlyClasses() {
1179        //Bug#3911318 All brokered sessions share the same DefaultReadOnlyClasses.
1180
if (hasBroker()) {
1181            return getBroker().getDefaultReadOnlyClasses();
1182        }
1183        return getProject().getDefaultReadOnlyClasses();
1184    }
1185
1186    /**
1187     * ADVANCED:
1188     * Return the descriptor specified for the class.
1189     * If the class does not have a descriptor but implements an interface that is also implemented
1190     * by one of the classes stored in the hashtable, that descriptor will be stored under the
1191     * new class.
1192     */

1193    public ClassDescriptor getClassDescriptor(Class JavaDoc theClass) {
1194        ClassDescriptor desc = getDescriptor(theClass);
1195        if (desc instanceof ClassDescriptor) {
1196            return (ClassDescriptor)desc;
1197        } else {
1198            throw ValidationException.cannotCastToClass(desc, desc.getClass(), ClassDescriptor.class);
1199        }
1200    }
1201
1202    /**
1203     * ADVANCED:
1204     * Return the descriptor specified for the object's class.
1205     */

1206    public ClassDescriptor getClassDescriptor(Object JavaDoc domainObject) {
1207        ClassDescriptor desc = getDescriptor(domainObject);
1208        if (desc instanceof ClassDescriptor) {
1209            return (ClassDescriptor)desc;
1210        } else {
1211            throw ValidationException.cannotCastToClass(desc, desc.getClass(), ClassDescriptor.class);
1212        }
1213    }
1214
1215    /**
1216     * PUBLIC:
1217     * Return the descriptor for the alias.
1218     * UnitOfWork delegates this to the parent
1219     */

1220    public ClassDescriptor getClassDescriptorForAlias(String JavaDoc alias) {
1221        return project.getClassDescriptorForAlias(alias);
1222    }
1223
1224    /**
1225     * ADVANCED:
1226     * Return the descriptor specified for the class.
1227     * If the class does not have a descriptor but implements an interface that is also implemented
1228     * by one of the classes stored in the hashtable, that descriptor will be stored under the
1229     * new class.
1230     */

1231    public ClassDescriptor getDescriptor(Class JavaDoc theClass) {
1232        if (theClass == null) {
1233            return null;
1234        }
1235
1236        // Optimize descriptor lookup through caching the last one accessed.
1237
ClassDescriptor lastDescriptor = this.lastDescriptorAccessed;
1238        if ((lastDescriptor != null) && (lastDescriptor.getJavaClass().equals(theClass))) {
1239            return lastDescriptor;
1240        }
1241
1242        ClassDescriptor descriptor = (ClassDescriptor)getDescriptors().get(theClass);
1243
1244        if ((descriptor == null) && hasBroker()) {
1245            // Also check the broker
1246
descriptor = getBroker().getDescriptor(theClass);
1247        }
1248        if (descriptor == null) {
1249            // Allow for an event listener to lazy register the descriptor for a class.
1250
getEventManager().missingDescriptor(theClass);
1251            descriptor = (ClassDescriptor)getDescriptors().get(theClass);
1252        }
1253
1254        if (descriptor == null) {
1255            // This allows for the correct descriptor to be found if the class implements an interface,
1256
// or extends a class that a descriptor is register for.
1257
// This is used by EJB to find the descriptor for a stub and remote to unwrap it,
1258
// and by inheritance to allow for subclasses that have no additional state to not require a descriptor.
1259
if (!theClass.isInterface()) {
1260                Class JavaDoc[] interfaces = theClass.getInterfaces();
1261                for (int index = 0; index < interfaces.length; ++index) {
1262                    Class JavaDoc interfaceClass = (Class JavaDoc)interfaces[index];
1263                    descriptor = getDescriptor(interfaceClass);
1264                    if (descriptor != null) {
1265                        getDescriptors().put(interfaceClass, descriptor);
1266                        break;
1267                    }
1268                }
1269                if (descriptor == null) {
1270                    descriptor = getDescriptor(theClass.getSuperclass());
1271                }
1272            }
1273        }
1274
1275        // Cache for optimization.
1276
this.lastDescriptorAccessed = descriptor;
1277
1278        return descriptor;
1279    }
1280
1281    /**
1282     * ADVANCED:
1283     * Return the descriptor specified for the object's class.
1284     */

1285    public ClassDescriptor getDescriptor(Object JavaDoc domainObject) {
1286        return getDescriptor(domainObject.getClass());
1287    }
1288
1289    /**
1290     * PUBLIC:
1291     * Return the descriptor for the alias
1292     */

1293    public ClassDescriptor getDescriptorForAlias(String JavaDoc alias) {
1294        return project.getDescriptorForAlias(alias);
1295    }
1296
1297    /**
1298     * ADVANCED:
1299     * Return all registered descriptors.
1300     */

1301    public Map getDescriptors() {
1302        return getProject().getDescriptors();
1303    }
1304
1305    /**
1306     * ADVANCED:
1307     * Return all pre-defined not yet parsed EJBQL queries.
1308     * @see #getAllQueries()
1309     */

1310    public List getEjbqlPlaceHolderQueries() {
1311        // PERF: lazy init, not normally required.
1312
if (ejbqlPlaceHolderQueries == null) {
1313            ejbqlPlaceHolderQueries = new Vector();
1314        }
1315        return ejbqlPlaceHolderQueries;
1316    }
1317
1318    /**
1319     * PUBLIC:
1320     * Return the event manager.
1321     * The event manager can be used to register for various session events.
1322     */

1323    public synchronized SessionEventManager getEventManager() {
1324        if (eventManager == null) {
1325            // PERF: lazy init.
1326
eventManager = new SessionEventManager(this);
1327        }
1328        return eventManager;
1329    }
1330
1331    /**
1332     * INTERNAL:
1333     * Return a string which represents my ExceptionHandler's class
1334     * Added for F2104: Properties.xml
1335     * - gn
1336     */

1337    public String JavaDoc getExceptionHandlerClass() {
1338        String JavaDoc className = null;
1339        try {
1340            className = getExceptionHandler().getClass().getName();
1341        } catch (Exception JavaDoc exception) {
1342            return null;
1343        }
1344        return className;
1345    }
1346
1347    /**
1348     * PUBLIC:
1349     * Return the ExceptionHandler.Exception handler can catch errors that occur on queries or during database access.
1350     */

1351    public ExceptionHandler getExceptionHandler() {
1352        return exceptionHandler;
1353    }
1354
1355    /**
1356     * PUBLIC:
1357     * Used for JTS integration. If your application requires to have JTS control transactions instead of TopLink an
1358     * external transaction controler must be specified.
1359     * TopLink provides JTS controlers for several JTS implementations including JTS 1.0, Weblogic 5.1 and WebSphere 3.0.
1360     *
1361     * @see oracle.toplink.essentials.transaction.JTATransactionController
1362     */

1363    public ExternalTransactionController getExternalTransactionController() {
1364        return externalTransactionController;
1365    }
1366
1367    /**
1368     * PUBLIC:
1369     * The IdentityMapAccessor is the preferred way of accessing IdentityMap funcitons
1370     * This will return an object which implements an interface which exposes all public
1371     * IdentityMap functions.
1372     */

1373    public oracle.toplink.essentials.sessions.IdentityMapAccessor getIdentityMapAccessor() {
1374        return identityMapAccessor;
1375    }
1376
1377    /**
1378     * INTERNAL:
1379     * Return the internally available IdentityMapAccessor instance.
1380     */

1381    public oracle.toplink.essentials.internal.sessions.IdentityMapAccessor getIdentityMapAccessorInstance() {
1382        return identityMapAccessor;
1383    }
1384
1385    /**
1386     * PUBLIC:
1387     * Returns the integrityChecker.IntegrityChecker holds all the Descriptor Exceptions.
1388     */

1389    public IntegrityChecker getIntegrityChecker() {
1390        // BUG# 2700595 - Lazily create an IntegrityChecker if one has not already been created.
1391
if (integrityChecker == null) {
1392            integrityChecker = new IntegrityChecker();
1393        }
1394
1395        return integrityChecker;
1396    }
1397
1398    /**
1399     * PUBLIC:
1400     * Return the writer to which an accessor writes logged messages and SQL.
1401     * If not set, this reference defaults to a writer on System.out.
1402     *
1403     * @see #getSessionLog()
1404     */

1405    public Writer getLog() {
1406        return getSessionLog().getWriter();
1407    }
1408
1409    /**
1410     * INTERNAL:
1411     * Return the name of the session: class name + system hashcode.
1412     * <p>
1413     * This should be the implementation of toString(), and also the
1414     * value should be calculated in the constructor for it is used all the
1415     * time. However everything is lazily initialized now and the value is
1416     * transient for the system hashcode could vary?
1417     */

1418    public String JavaDoc getLogSessionString() {
1419        if (logSessionString == null) {
1420            StringWriter writer = new StringWriter();
1421            writer.write(getSessionTypeString());
1422            writer.write("(");
1423            writer.write(String.valueOf(System.identityHashCode(this)));
1424            writer.write(")");
1425            logSessionString = writer.toString();
1426        }
1427        return logSessionString;
1428    }
1429
1430    /**
1431     * INTERNAL:
1432     * Returns the type of session, its class.
1433     * <p>
1434     * Override to hide from the user when they are using an internal subclass
1435     * of a known class.
1436     * <p>
1437     * A user does not need to know that their UnitOfWork is a
1438     * non-deferred UnitOfWork, or that their ClientSession is an
1439     * IsolatedClientSession.
1440     */

1441    public String JavaDoc getSessionTypeString() {
1442        return Helper.getShortClassName(getClass());
1443    }
1444
1445    /**
1446     * INTERNAL:
1447     * Return the login, the login holds any database connection information given.
1448     * This has been replaced by getDatasourceLogin to make use of the Login interface
1449     * to support non-relational datasources,
1450     * if DatabaseLogin API is required it will need to be cast.
1451     */

1452    public DatabaseLogin getLogin() {
1453        try {
1454            return (DatabaseLogin)getDatasourceLogin();
1455        } catch (ClassCastException JavaDoc wrongType) {
1456            throw ValidationException.notSupportedForDatasource();
1457        }
1458    }
1459
1460    /**
1461     * PUBLIC:
1462     * Return the login, the login holds any database connection information given.
1463     * This return the Login interface and may need to be cast to the datasource specific implementation.
1464     */

1465    public Login getDatasourceLogin() {
1466        return getProject().getDatasourceLogin();
1467    }
1468
1469    /**
1470     * PUBLIC:
1471     * Return the name of the session.
1472     * This is used with the session broker, or to give the session a more meaningful name.
1473     */

1474    public String JavaDoc getName() {
1475        return name;
1476    }
1477
1478    /**
1479     * ADVANCED:
1480     * Return the sequnce number from the database
1481     */

1482    public Number JavaDoc getNextSequenceNumberValue(Class JavaDoc domainClass) {
1483        return (Number JavaDoc)getSequencing().getNextValue(domainClass);
1484    }
1485
1486    /**
1487     * INTERNAL:
1488     * Return the number of units of work connected.
1489     */

1490    public int getNumberOfActiveUnitsOfWork() {
1491        return numberOfActiveUnitsOfWork;
1492    }
1493
1494    /**
1495     * PUBLIC:
1496     * Return the database platform currently connected to.
1497     * The platform is used for database specific behavoir.
1498     * NOTE: this must only be used for relational specific usage,
1499     * it will fail for non-relational datasources.
1500     */

1501    public DatabasePlatform getPlatform() {
1502        return getDatasourceLogin().getPlatform();
1503    }
1504
1505    /**
1506     * PUBLIC:
1507     * Return the database platform currently connected to.
1508     * The platform is used for database specific behavoir.
1509     */

1510    public Platform getDatasourcePlatform() {
1511        // PERF: Cache the platform.
1512
if (platform == null) {
1513            platform = getDatasourceLogin().getDatasourcePlatform();
1514        }
1515        return platform;
1516    }
1517    
1518    /**
1519     * INTERNAL:
1520     * Marked internal as this is not customer API but helper methods for
1521     * accessing the server platform from within TopLink's other sessions types
1522     * (ie not DatabaseSession)
1523     */

1524    public ServerPlatform getServerPlatform(){
1525        return null;
1526    }
1527
1528    /**
1529     * INTERNAL:
1530     * Return the database platform currently connected to
1531     * for specified class.
1532     * The platform is used for database specific behavoir.
1533     */

1534    public Platform getPlatform(Class JavaDoc domainClass) {
1535        // PERF: Cache the platform.
1536
if (platform == null) {
1537            platform = getDatasourcePlatform();
1538        }
1539        return platform;
1540    }
1541
1542    /**
1543     * PUBLIC:
1544     * Return the profiler.
1545     * The profiler is a tool that can be used to determine performance bottlenecks.
1546     * The profiler can be queries to print summaries and configure for logging purposes.
1547     */

1548    public SessionProfiler getProfiler() {
1549        return profiler;
1550    }
1551
1552    /**
1553     * PUBLIC:
1554     * Return the project, the project holds configuartion information including the descriptors.
1555     */

1556    public oracle.toplink.essentials.sessions.Project getProject() {
1557        return project;
1558    }
1559
1560    /**
1561     * ADVANCED:
1562     * Allow for user defined properties.
1563     */

1564    public Map getProperties() {
1565        if (properties == null) {
1566            properties = new HashMap(5);
1567        }
1568        return properties;
1569    }
1570
1571    /**
1572     * INTERNAL:
1573     * Allow to check for user defined properties.
1574     */

1575    public boolean hasProperties() {
1576        return ((properties != null) && !properties.isEmpty());
1577    }
1578
1579    /**
1580     * ADVANCED:
1581     * Returns the user defined property.
1582     */

1583    public Object JavaDoc getProperty(String JavaDoc name) {
1584        return getProperties().get(name);
1585    }
1586
1587    /**
1588     * ADVANCED:
1589     * Return all pre-defined queries.
1590     * @see #getAllQueries()
1591     */

1592    public Map getQueries() {
1593        // PERF: lazy init, not normally required.
1594
if (queries == null) {
1595            queries = new HashMap(5);
1596        }
1597        return queries;
1598    }
1599
1600    /**
1601     * PUBLIC:
1602     * Return the pre-defined queries in this session.
1603     * A single vector containing all the queries is returned.
1604     *
1605     * @see #getQueries()
1606     */

1607    public Vector getAllQueries() {
1608        Vector allQueries = new Vector();
1609        for (Iterator vectors = getQueries().values().iterator(); vectors.hasNext();) {
1610            allQueries.addAll((Vector)vectors.next());
1611        }
1612        return allQueries;
1613    }
1614
1615    /**
1616     * PUBLIC:
1617     * Return the query from the session pre-defined queries with the given name.
1618     * This allows for common queries to be pre-defined, reused and executed by name.
1619     */

1620    public DatabaseQuery getQuery(String JavaDoc name) {
1621        return getQuery(name, null);
1622    }
1623
1624    /**
1625     * PUBLIC:
1626     * Return the query from the session pre-defined queries with the given name and argument types.
1627     * This allows for common queries to be pre-defined, reused and executed by name.
1628     * This method should be used if the Session has multiple queries with the same name but
1629     * different arguments.
1630     *
1631     * @see #getQuery(String)
1632     */

1633    public DatabaseQuery getQuery(String JavaDoc name, Vector arguments) {
1634        Vector queries = (Vector)getQueries().get(name);
1635        if ((queries == null) || queries.isEmpty()) {
1636            return null;
1637        }
1638
1639        // Short circuit the simple, most common case of only one query.
1640
if (queries.size() == 1) {
1641            return (DatabaseQuery)queries.firstElement();
1642        }
1643
1644        // CR#3754; Predrag; mar 19/2002;
1645
// We allow multiple named queries with the same name but
1646
// different argument set; we can have only one query with
1647
// no arguments; Vector queries is not sorted;
1648
// When asked for the query with no parameters the
1649
// old version did return the first query - wrong:
1650
// return (DatabaseQuery) queries.firstElement();
1651
int argumentTypesSize = 0;
1652        if (arguments != null) {
1653            argumentTypesSize = arguments.size();
1654        }
1655        Vector argumentTypes = new Vector(argumentTypesSize);
1656        for (int i = 0; i < argumentTypesSize; i++) {
1657            argumentTypes.addElement(arguments.elementAt(i).getClass());
1658        }
1659        for (Enumeration queriesEnum = queries.elements(); queriesEnum.hasMoreElements();) {
1660            DatabaseQuery query = (DatabaseQuery)queriesEnum.nextElement();
1661            if (Helper.areTypesAssignable(argumentTypes, query.getArgumentTypes())) {
1662                return query;
1663            }
1664        }
1665        return null;
1666    }
1667
1668    /**
1669     * INTERNAL:
1670     * Return the Sequencing object used by the session.
1671     */

1672    public Sequencing getSequencing() {
1673        return null;
1674    }
1675
1676    /**
1677     * INTERNAL:
1678     * Return the session to be used for the class.
1679     * Used for compatibility with the session broker.
1680     */

1681    public AbstractSession getSessionForClass(Class JavaDoc domainClass) {
1682        if (hasBroker()) {
1683            return getBroker().getSessionForClass(domainClass);
1684        }
1685        return this;
1686    }
1687
1688    /**
1689     * PUBLIC:
1690     * Return the session log to which an accessor logs messages and SQL.
1691     * If not set, this will default to a session log on a writer on System.out.
1692     */

1693    public SessionLog getSessionLog() {
1694        if (sessionLog == null) {
1695            setSessionLog(new DefaultSessionLog());
1696        }
1697        return sessionLog;
1698    }
1699
1700    /**
1701     * INTERNAL:
1702     * The transaction mutex ensure mutual exclusion on transaction across multiple threads.
1703     */

1704    public synchronized ConcurrencyManager getTransactionMutex() {
1705        // PERF: not always required, defer.
1706
if (transactionMutex == null) {
1707            transactionMutex = new ConcurrencyManager();
1708        }
1709        return transactionMutex;
1710    }
1711
1712    /**
1713     * PUBLIC:
1714     * Allow any WARNING level exceptions that occur within TopLink to be logged and handled by the exception handler.
1715     */

1716    public Object JavaDoc handleException(RuntimeException JavaDoc exception) throws RuntimeException JavaDoc {
1717        if ((exception instanceof TopLinkException)) {
1718            TopLinkException topLinkException = (TopLinkException)exception;
1719            if (topLinkException.getSession() == null) {
1720                topLinkException.setSession(this);
1721            }
1722            //Bug#3559280 Avoid logging an exception twice
1723
if (!topLinkException.hasBeenLogged()) {
1724                logThrowable(SessionLog.WARNING, null, exception);
1725                topLinkException.setHasBeenLogged(true);
1726            }
1727        } else {
1728            logThrowable(SessionLog.WARNING, null, exception);
1729        }
1730        if (hasExceptionHandler()) {
1731            return getExceptionHandler().handleException(exception);
1732        } else {
1733            throw exception;
1734        }
1735    }
1736
1737    /**
1738     * INTERNAL:
1739     * Allow the session to be used from a session broker.
1740     */

1741    public boolean hasBroker() {
1742        return broker != null;
1743    }
1744
1745    /**
1746     * ADVANCED:
1747     * Return true if a descriptor exists for the given class.
1748     */

1749    public boolean hasDescriptor(Class JavaDoc theClass) {
1750        if (theClass == null) {
1751            return false;
1752        }
1753
1754        return getDescriptors().get(theClass) != null;
1755    }
1756
1757    /**
1758     * PUBLIC:
1759     * Return if an exception handler is present.
1760     */

1761    public boolean hasExceptionHandler() {
1762        if (exceptionHandler == null) {
1763            return false;
1764        }
1765        return true;
1766    }
1767
1768    /**
1769     * PUBLIC:
1770     * Used for JTA integration. If your application requires to have JTA control transactions instead of TopLink an
1771     * external transaction controler must be specified. TopLink provides JTA controlers for JTA 1.0 and application
1772     * servers.
1773     * @see oracle.toplink.essentials.transaction.JTATransactionController
1774     */

1775    public boolean hasExternalTransactionController() {
1776        return externalTransactionController != null;
1777    }
1778
1779    /**
1780     * INTERNAL:
1781     * Set up the IdentityMapManager. This method allows subclasses of Session to override
1782     * the default IdentityMapManager functionality.
1783     */

1784    public void initializeIdentityMapAccessor() {
1785        this.identityMapAccessor = new oracle.toplink.essentials.internal.sessions.IdentityMapAccessor(this, new IdentityMapManager(this));
1786    }
1787
1788    /**
1789     * PUBLIC:
1790     * Insert the object and all of its privately owned parts into the database.
1791     * Insert should only be used if the application knows that the object is new,
1792     * otherwise writeObject should be used.
1793     * The insert operation can be customized through using an insert query.
1794     *
1795     * @exception DatabaseException if an error occurs on the database,
1796     * these include constraint violations, security violations and general database erros.
1797     *
1798     * @see InsertObjectQuery
1799     * @see #writeObject(Object)
1800     */

1801    public Object JavaDoc insertObject(Object JavaDoc domainObject) throws DatabaseException {
1802        InsertObjectQuery query = new InsertObjectQuery();
1803        query.setObject(domainObject);
1804        return executeQuery(query);
1805    }
1806
1807    /**
1808     * INTERNAL:
1809     * Return the results from exeucting the database query.
1810     * The arguments should be a database row with raw data values.
1811     * This method is provided to allow subclasses to change the default querying behavoir.
1812     * All querying goes through this method.
1813     */

1814    public Object JavaDoc internalExecuteQuery(DatabaseQuery query, AbstractRecord databaseRow) throws DatabaseException {
1815        return query.execute(this, databaseRow);
1816    }
1817
1818    /**
1819     * INTERNAL:
1820     * Returns true if the session is a session Broker.
1821     */

1822    public boolean isBroker() {
1823        return false;
1824    }
1825
1826    /**
1827     * INTERNAL:
1828     * Returns true if the session is in a session Broker.
1829     */

1830    public boolean isInBroker() {
1831        return false;
1832    }
1833
1834    /**
1835     * PUBLIC:
1836     * Return if the class is defined as read-only.
1837     */

1838    public boolean isClassReadOnly(Class JavaDoc theClass) {
1839        ClassDescriptor descriptor = getDescriptor(theClass);
1840        return isClassReadOnly(theClass, descriptor);
1841    }
1842
1843    /**
1844     * INTERNAL:
1845     * Return if the class is defined as read-only.
1846     * PERF: Pass descriptor to avoid re-lookup.
1847     */

1848    public boolean isClassReadOnly(Class JavaDoc theClass, ClassDescriptor descriptor) {
1849        if ((descriptor != null) && descriptor.shouldBeReadOnly()) {
1850            return true;
1851        }
1852        if (theClass != null) {
1853            return getDefaultReadOnlyClasses().contains(theClass);
1854        }
1855        return false;
1856    }
1857
1858    /**
1859     * PUBLIC:
1860     * Return if this session is a client session.
1861     */

1862    public boolean isClientSession() {
1863        return false;
1864    }
1865
1866    /**
1867     * PUBLIC:
1868     * Return if this session is connected to the database.
1869     */

1870    public boolean isConnected() {
1871        if (getAccessor() == null) {
1872            return false;
1873        }
1874
1875        return getAccessor().isConnected();
1876    }
1877
1878    /**
1879     * PUBLIC:
1880     * Return if this session is a database session.
1881     */

1882    public boolean isDatabaseSession() {
1883        return false;
1884    }
1885
1886    /**
1887     * PUBLIC:
1888     * Return if this session is a distributed session.
1889     */

1890    public boolean isDistributedSession() {
1891        return false;
1892    }
1893
1894    /**
1895     * PUBLIC:
1896     * Return if a profiler is being used.
1897     */

1898    public boolean isInProfile() {
1899        return isInProfile;
1900    }
1901
1902    /**
1903     * PUBLIC:
1904     * Allow for user deactive a profiler
1905     */

1906    public void setIsInProfile(boolean inProfile) {
1907        this.isInProfile = inProfile;
1908    }
1909
1910    /**
1911     * PUBLIC:
1912     * Return if the session is currently in the progress of a database transaction.
1913     * Because nested transactions are allowed check if the transaction mutex has been aquired.
1914     */

1915    public boolean isInTransaction() {
1916        return getTransactionMutex().isAcquired();
1917    }
1918
1919    /**
1920     * PUBLIC:
1921     * Return if this session is remote.
1922     */

1923    public boolean isRemoteSession() {
1924        return false;
1925    }
1926
1927    /**
1928     * PUBLIC:
1929     * Return if this session is a unit of work.
1930     */

1931    public boolean isRemoteUnitOfWork() {
1932        return false;
1933    }
1934
1935    /**
1936     * PUBLIC:
1937     * Return if this session is a server session.
1938     */

1939    public boolean isServerSession() {
1940        return false;
1941    }
1942
1943    /**
1944     * PUBLIC:
1945     * Return if this session is a session broker.
1946     */

1947    public boolean isSessionBroker() {
1948        return false;
1949    }
1950
1951    /**
1952     * PUBLIC:
1953     * Return if this session is a unit of work.
1954     */

1955    public boolean isUnitOfWork() {
1956        return false;
1957    }
1958
1959    /**
1960     * ADVANCED:
1961     * Extract and return the primary key from the object.
1962     */

1963    public Vector keyFromObject(Object JavaDoc domainObject) throws ValidationException {
1964        ClassDescriptor descriptor = getDescriptor(domainObject);
1965        return keyFromObject(domainObject, descriptor);
1966    }
1967
1968    /**
1969     * ADVANCED:
1970     * Extract and return the primary key from the object.
1971     */

1972    public Vector keyFromObject(Object JavaDoc domainObject, ClassDescriptor descriptor) throws ValidationException {
1973        if (descriptor == null) {
1974            throw ValidationException.missingDescriptor(domainObject.getClass().getName());
1975        }
1976        Object JavaDoc implemention = descriptor.getObjectBuilder().unwrapObject(domainObject, this);
1977        if (implemention == null) {
1978            return null;
1979        }
1980        return descriptor.getObjectBuilder().extractPrimaryKeyFromObject(implemention, this);
1981    }
1982
1983    /**
1984     * PUBLIC:
1985     * Log the log entry.
1986     */

1987    public void log(SessionLogEntry entry) {
1988        if (shouldLog(entry.getLevel(), entry.getNameSpace())) {
1989            if (entry.getSession() == null) {// Used for proxy session.
1990
entry.setSession(this);
1991            }
1992            getSessionLog().log(entry);
1993        }
1994    }
1995
1996    /**
1997     * Log a untranslated message to the TopLink log at FINER level.
1998     */

1999    public void logMessage(String JavaDoc message) {
2000        log(SessionLog.FINER, message, (Object JavaDoc[])null, null, false);
2001    }
2002
2003    /**
2004     * INTERNAL:
2005     * A call back to do session specific preparation of a query.
2006     * <p>
2007     * The call back occurs soon before we clone the query for execution,
2008     * meaning that if this method needs to clone the query then the caller will
2009     * determine that it doesn't need to clone the query itself.
2010     */

2011    public DatabaseQuery prepareDatabaseQuery(DatabaseQuery query) {
2012        if (!isUnitOfWork() && query.isObjectLevelReadQuery()) {
2013            return ((ObjectLevelReadQuery)query).prepareOutsideUnitOfWork(this);
2014        } else {
2015            return query;
2016        }
2017    }
2018    
2019    /**
2020     * INTERNAL:
2021     * Allows for EJBQL strings to be parsed and added as named queries. Should
2022     * be called after descriptors have been initialized to ensure all mappings
2023     * exist.
2024     */

2025    public void processEJBQLQueries() {
2026        List queries = getEjbqlPlaceHolderQueries();
2027        processEJBQLQueries(queries);
2028        queries.clear();
2029    }
2030    
2031        /**
2032     * INTERNAL:
2033     * Allows for EJBQL strings to be parsed and added as named queries. Should
2034     * be called after descriptors have been initialized to ensure all mappings
2035     * exist.
2036     */

2037    public void processEJBQLQueries(List queries) {
2038        for (Iterator iterator = queries.iterator(); iterator.hasNext();) {
2039            EJBQLPlaceHolderQuery existingQuery = (EJBQLPlaceHolderQuery)iterator.next();
2040            this.addQuery(existingQuery.processEjbQLQuery(this));
2041        }
2042    }
2043
2044    /**
2045     * PUBLIC:
2046     * Read all of the instances of the class from the database.
2047     * This operation can be customized through using a ReadAllQuery,
2048     * or through also passing in a selection criteria.
2049     *
2050     * @see ReadAllQuery
2051     * @see #readAllObjects(Class, Expression)
2052     */

2053    public Vector readAllObjects(Class JavaDoc domainClass) throws DatabaseException {
2054        ReadAllQuery query = new ReadAllQuery();
2055        query.setReferenceClass(domainClass);
2056        return (Vector)executeQuery(query);
2057    }
2058
2059    /**
2060     * PUBLIC:
2061     * Read all of the instances of the class from the database return through execution the SQL string.
2062     * The SQL string must be a valid SQL select statement or selecting stored procedure call.
2063     * This operation can be customized through using a ReadAllQuery.
2064     *
2065     * @see ReadAllQuery
2066     */

2067    public Vector readAllObjects(Class JavaDoc domainClass, String JavaDoc sqlString) throws DatabaseException {
2068        ReadAllQuery query = new ReadAllQuery();
2069        query.setReferenceClass(domainClass);
2070        query.setSQLString(sqlString);
2071        return (Vector)executeQuery(query);
2072    }
2073
2074    /**
2075     * PUBLIC:
2076     * Read all the instances of the class from the database returned through execution the Call string.
2077     * The Call can be an SQLCall or EJBQLCall.
2078     *
2079     * example: session.readAllObjects(Employee.class, new SQLCall("SELECT * FROM EMPLOYEE"));
2080     * @see Call
2081     */

2082    public Vector readAllObjects(Class JavaDoc referenceClass, Call aCall) throws DatabaseException {
2083        ReadAllQuery raq = new ReadAllQuery();
2084        raq.setReferenceClass(referenceClass);
2085        raq.setCall(aCall);
2086        return (Vector)executeQuery(raq);
2087    }
2088
2089    /**
2090     * PUBLIC:
2091     * Read all of the instances of the class from the database matching the given expression.
2092     * This operation can be customized through using a ReadAllQuery.
2093     *
2094     * @see ReadAllQuery
2095     */

2096    public Vector readAllObjects(Class JavaDoc domainClass, Expression expression) throws DatabaseException {
2097        ReadAllQuery query = new ReadAllQuery();
2098        query.setReferenceClass(domainClass);
2099        query.setSelectionCriteria(expression);
2100        return (Vector)executeQuery(query);
2101    }
2102
2103    /**
2104     * PUBLIC:
2105     * Read the first instance of the class from the database.
2106     * This operation can be customized through using a ReadObjectQuery,
2107     * or through also passing in a selection criteria.
2108     *
2109     * @see ReadObjectQuery
2110     * @see #readAllObjects(Class, Expression)
2111     */

2112    public Object JavaDoc readObject(Class JavaDoc domainClass) throws DatabaseException {
2113        ReadObjectQuery query = new ReadObjectQuery();
2114        query.setReferenceClass(domainClass);
2115        return executeQuery(query);
2116    }
2117
2118    /**
2119     * PUBLIC:
2120     * Read the first instance of the class from the database return through execution the SQL string.
2121     * The SQL string must be a valid SQL select statement or selecting stored procedure call.
2122     * This operation can be customized through using a ReadObjectQuery.
2123     *
2124     * @see ReadObjectQuery
2125     */

2126    public Object JavaDoc readObject(Class JavaDoc domainClass, String JavaDoc sqlString) throws DatabaseException {
2127        ReadObjectQuery query = new ReadObjectQuery();
2128        query.setReferenceClass(domainClass);
2129        query.setSQLString(sqlString);
2130        return executeQuery(query);
2131    }
2132
2133    /**
2134     * PUBLIC:
2135     * Read the first instance of the class from the database returned through execution the Call string.
2136     * The Call can be an SQLCall or EJBQLCall.
2137     *
2138     * example: session.readObject(Employee.class, new SQLCall("SELECT * FROM EMPLOYEE"));
2139     * @see SQLCall
2140     * @see EJBQLCall
2141     */

2142    public Object JavaDoc readObject(Class JavaDoc domainClass, Call aCall) throws DatabaseException {
2143        ReadObjectQuery query = new ReadObjectQuery();
2144        query.setReferenceClass(domainClass);
2145        query.setCall(aCall);
2146        return executeQuery(query);
2147    }
2148
2149    /**
2150     * PUBLIC:
2151     * Read the first instance of the class from the database matching the given expression.
2152     * This operation can be customized through using a ReadObjectQuery.
2153     *
2154     * @see ReadObjectQuery
2155     */

2156    public Object JavaDoc readObject(Class JavaDoc domainClass, Expression expression) throws DatabaseException {
2157        ReadObjectQuery query = new ReadObjectQuery();
2158        query.setReferenceClass(domainClass);
2159        query.setSelectionCriteria(expression);
2160        return executeQuery(query);
2161    }
2162
2163    /**
2164     * PUBLIC:
2165     * Use the example object to consruct a read object query by the objects primary key.
2166     * This will read the object from the database with the same primary key as the object
2167     * or null if no object is found.
2168     */

2169    public Object JavaDoc readObject(Object JavaDoc object) throws DatabaseException {
2170        ReadObjectQuery query = new ReadObjectQuery();
2171        query.setSelectionObject(object);
2172        return executeQuery(query);
2173    }
2174
2175    /**
2176     * PUBLIC:
2177     * Refresh the attributes of the object and of all of its private parts from the database.
2178     * The object will be pessimisticly locked on the database for the duration of the transaction.
2179     * If the object is already locked this method will wait until the lock is released.
2180     * A no wait option is available through setting the lock mode.
2181     * @see #refreshAndLockObject(Object, lockMode)
2182     */

2183    public Object JavaDoc refreshAndLockObject(Object JavaDoc object) throws DatabaseException {
2184        ReadObjectQuery query = new ReadObjectQuery();
2185        query.setSelectionObject(object);
2186        query.refreshIdentityMapResult();
2187        query.cascadePrivateParts();
2188        query.setLockMode(ObjectBuildingQuery.LOCK);
2189        return executeQuery(query);
2190    }
2191
2192    /**
2193     * PUBLIC:
2194     * Refresh the attributes of the object and of all of its private parts from the database.
2195     * The object will be pessimisticly locked on the database for the duration of the transaction.
2196     * <p>Lock Modes: ObjectBuildingQuery.NO_LOCK, LOCK, LOCK_NOWAIT
2197     */

2198    public Object JavaDoc refreshAndLockObject(Object JavaDoc object, short lockMode) throws DatabaseException {
2199        ReadObjectQuery query = new ReadObjectQuery();
2200        query.setSelectionObject(object);
2201        query.refreshIdentityMapResult();
2202        query.cascadePrivateParts();
2203        query.setLockMode(lockMode);
2204        return executeQuery(query);
2205    }
2206
2207    /**
2208     * PUBLIC:
2209     * Refresh the attributes of the object and of all of its private parts from the database.
2210     * This can be used to ensure the object is up to date with the database.
2211     * Caution should be used when using this to make sure the application has no un commited
2212     * changes to the object.
2213     */

2214    public Object JavaDoc refreshObject(Object JavaDoc object) throws DatabaseException {
2215        return refreshAndLockObject(object, ObjectBuildingQuery.NO_LOCK);
2216    }
2217
2218    /**
2219     * PUBLIC:
2220     * Release the session.
2221     * This does nothing by default, but allows for other sessions such as the ClientSession to do something.
2222     */

2223    public void release() {
2224    }
2225
2226    /**
2227     * INTERNAL:
2228     * Release the unit of work, if lazy release the connection.
2229     */

2230    public void releaseUnitOfWork(UnitOfWorkImpl unitOfWork) {
2231        // Nothing is required by default, allow subclasses to do cleanup.
2232
setNumberOfActiveUnitsOfWork(getNumberOfActiveUnitsOfWork() - 1);
2233    }
2234
2235
2236    /**
2237     * PUBLIC:
2238     * Remove the user defined property.
2239     */

2240    public void removeProperty(String JavaDoc property) {
2241        getProperties().remove(property);
2242    }
2243
2244    /**
2245     * PUBLIC:
2246     * Remove all queries with the given queryName regardless of the argument types.
2247     *
2248     * @see #removeQuery(String, Vector)
2249     */

2250    public void removeQuery(String JavaDoc queryName) {
2251        getQueries().remove(queryName);
2252    }
2253
2254    /**
2255     * PUBLIC:
2256     * Remove the specific query with the given queryName and argumentTypes.
2257     */

2258    public void removeQuery(String JavaDoc queryName, Vector argumentTypes) {
2259        Vector queries = (Vector)getQueries().get(queryName);
2260        if (queries == null) {
2261            return;
2262        } else {
2263            DatabaseQuery query = null;
2264            for (Enumeration enumtr = queries.elements(); enumtr.hasMoreElements();) {
2265                query = (DatabaseQuery)enumtr.nextElement();
2266                if (Helper.areTypesAssignable(argumentTypes, query.getArgumentTypes())) {
2267                    break;
2268                }
2269            }
2270            if (query != null) {
2271                queries.remove(query);
2272            }
2273        }
2274    }
2275
2276    /**
2277     * PROTECTED:
2278     * Attempts to rollback the running internally started external transaction.
2279     * Returns true only in one case -
2280     * extenal transaction has been internally rolled back during this method call:
2281     * wasJTSTransactionInternallyStarted()==true in the beginning of this method and
2282     * wasJTSTransactionInternallyStarted()==false in the end of this method.
2283     */

2284    protected boolean rollbackExternalTransaction() {
2285        boolean externalTransactionHasRolledBack = false;
2286        if (hasExternalTransactionController() && wasJTSTransactionInternallyStarted()) {
2287            try {
2288                getExternalTransactionController().rollbackTransaction(this);
2289            } catch (RuntimeException JavaDoc exception) {
2290                handleException(exception);
2291            }
2292            if (!wasJTSTransactionInternallyStarted()) {
2293                externalTransactionHasRolledBack = true;
2294                log(SessionLog.FINER, SessionLog.TRANSACTION, "external_transaction_has_rolled_back_internally");
2295            }
2296        }
2297        return externalTransactionHasRolledBack;
2298    }
2299
2300    /**
2301     * PUBLIC:
2302     * Rollback the active database transaction.
2303     * This allows a group of database modification to be commited or rolledback as a unit.
2304     * All writes/deletes will be sent to the database be will not be visible to other users until commit.
2305     * Although databases do not allow nested transaction,
2306     * TopLink supports nesting through only committing to the database on the outer commit.
2307     *
2308     * @exception DatabaseException if the database connection is lost or the rollback fails.
2309     * @exception ConcurrencyException if this session is not within a transaction.
2310     */

2311    public void rollbackTransaction() throws DatabaseException, ConcurrencyException {
2312        // Ensure release of mutex and call subclass specific release.
2313
try {
2314            if (!getTransactionMutex().isNested()) {
2315                getEventManager().preRollbackTransaction();
2316                basicRollbackTransaction();
2317                getEventManager().postRollbackTransaction();
2318            }
2319        } finally {
2320            getTransactionMutex().release();
2321
2322            // If there is no db transaction in progress
2323
// if there is an active external transaction
2324
// which was started internally - it should be rolled back internally, too.
2325
if (!isInTransaction()) {
2326                rollbackExternalTransaction();
2327            }
2328        }
2329    }
2330
2331    /**
2332     * INTERNAL:
2333     * Set the accessor.
2334     */

2335    public void setAccessor(Accessor accessor) {
2336        this.accessor = accessor;
2337    }
2338
2339    /**
2340     * INTERNAL:
2341     * Allow the session to be used from a session broker.
2342     */

2343    public void setBroker(AbstractSession broker) {
2344        this.broker = broker;
2345    }
2346
2347    /**
2348     * INTERNAL:
2349     * The commit manager is used to resolve referncial integrity on commits of multiple objects.
2350     */

2351    public void setCommitManager(CommitManager commitManager) {
2352        this.commitManager = commitManager;
2353    }
2354
2355    /**
2356     * INTERNAL:
2357     * Set the event manager.
2358     * The event manager can be used to register for various session events.
2359     */

2360    public void setEventManager(SessionEventManager eventManager) {
2361        if (eventManager != null) {
2362            this.eventManager = eventManager;
2363        } else {
2364            this.eventManager = new SessionEventManager();
2365        }
2366        this.eventManager.setSession(this);
2367    }
2368
2369    /**
2370     * PUBLIC:
2371     * Set the exceptionHandler.
2372     * Exception handler can catch errors that occur on queries or during database access.
2373     */

2374    public void setExceptionHandler(ExceptionHandler exceptionHandler) {
2375        this.exceptionHandler = exceptionHandler;
2376    }
2377
2378    /**
2379     * Used for JTS integration internally by ServerPlatform.
2380     */

2381    public void setExternalTransactionController(ExternalTransactionController externalTransactionController) {
2382        this.externalTransactionController = externalTransactionController;
2383        if (externalTransactionController == null) {
2384            return;
2385        }
2386        externalTransactionController.setSession(this);
2387    }
2388
2389    /**
2390     * PUBLIC:
2391     * set the integrityChecker. IntegrityChecker holds all the Descriptor Exceptions.
2392     */

2393    public void setIntegrityChecker(IntegrityChecker integrityChecker) {
2394        this.integrityChecker = integrityChecker;
2395    }
2396
2397    /**
2398     * PUBLIC:
2399     * Set the writer to which an accessor writes logged messages and SQL.
2400     * If not set, this reference defaults to a writer on System.out.
2401     *
2402     * @see #setSessionLog(SessionLog)
2403     */

2404    public void setLog(Writer log) {
2405        getSessionLog().setWriter(log);
2406    }
2407
2408    /**
2409     * PUBLIC:
2410     * Set the login.
2411     */

2412    public void setLogin(DatabaseLogin login) {
2413        setDatasourceLogin(login);
2414    }
2415
2416    /**
2417     * PUBLIC:
2418     * Set the login.
2419     */

2420    public void setLogin(Login login) {
2421        setDatasourceLogin(login);
2422    }
2423
2424    /**
2425     * PUBLIC:
2426     * Set the login.
2427     */

2428    public void setDatasourceLogin(Login login) {
2429        getProject().setDatasourceLogin(login);
2430    }
2431
2432    /**
2433     * PUBLIC:
2434     * Set the name of the session.
2435     * This is used with the session broker.
2436     */

2437    public void setName(String JavaDoc name) {
2438        this.name = name;
2439    }
2440
2441    protected void setNumberOfActiveUnitsOfWork(int numberOfActiveUnitsOfWork) {
2442        this.numberOfActiveUnitsOfWork = numberOfActiveUnitsOfWork;
2443    }
2444
2445    /**
2446     * PUBLIC:
2447     * Set the profiler for the session.
2448     * This allows for performance operations to be profiled.
2449     */

2450    public void setProfiler(SessionProfiler profiler) {
2451        this.profiler = profiler;
2452        if (profiler != null) {
2453            profiler.setSession(this);
2454            setIsInProfile(getProfiler().getProfileWeight() != SessionProfiler.NONE);
2455            // Clear cached flag that bybasses the profiler check.
2456
getIdentityMapAccessorInstance().getIdentityMapManager().clearCacheAccessPreCheck();
2457        } else {
2458            setIsInProfile(false);
2459        }
2460    }
2461
2462    /**
2463     * INTERNAL:
2464     * Set the project, the project holds configuartion information including the descriptors.
2465     */

2466    public void setProject(oracle.toplink.essentials.sessions.Project project) {
2467        this.project = project;
2468    }
2469
2470    /**
2471     * INTERNAL:
2472     * Set the user defined properties.
2473     */

2474    public void setProperties(Hashtable properties) {
2475        this.properties = properties;
2476    }
2477
2478    /**
2479     * PUBLIC:
2480     * Allow for user defined properties.
2481     */

2482    public void setProperty(String JavaDoc propertyName, Object JavaDoc propertyValue) {
2483        getProperties().put(propertyName, propertyValue);
2484    }
2485
2486    protected void setQueries(Hashtable queries) {
2487        this.queries = queries;
2488    }
2489
2490    /**
2491     * PUBLIC:
2492     * Set the session log to which an accessor logs messages and SQL.
2493     * If not set, this will default to a session log on a writer on System.out.
2494     * To enable logging, log level can not be OFF.
2495     * Also set a backpointer to this session in SessionLog. To avoid a sessionLog
2496     * being shared by more than one session, it needs to be cloned.
2497     *
2498     * @see #logMessage(String)
2499     */

2500    public void setSessionLog(SessionLog sessionLog) {
2501        this.sessionLog = (SessionLog)((AbstractSessionLog)sessionLog).clone();
2502        if (this.sessionLog != null) {
2503            this.sessionLog.setSession(this);
2504        }
2505    }
2506
2507    protected void setTransactionMutex(ConcurrencyManager transactionMutex) {
2508        this.transactionMutex = transactionMutex;
2509    }
2510
2511    /**
2512     * INTERNAL:
2513     * Return if a JTS transaction was started by the session.
2514     * The session will start a JTS transaction if a unit of work or transaction is begun without a JTS transaction present.
2515     */

2516    public void setWasJTSTransactionInternallyStarted(boolean wasJTSTransactionInternallyStarted) {
2517        this.wasJTSTransactionInternallyStarted = wasJTSTransactionInternallyStarted;
2518    }
2519
2520    /**
2521     * PUBLIC:
2522     * Return if logging is enabled (false if log level is OFF)
2523     */

2524    public boolean shouldLogMessages() {
2525        if (getLogLevel(null) == SessionLog.OFF) {
2526            return false;
2527        } else {
2528            return true;
2529        }
2530    }
2531
2532    /**
2533     * INTERNAL:
2534     * Start the operation timing.
2535     */

2536    public void startOperationProfile(String JavaDoc operationName) {
2537        if (isInProfile()) {
2538            getProfiler().startOperationProfile(operationName);
2539        }
2540    }
2541
2542    /**
2543     * Print the connection status with the session.
2544     */

2545    public String JavaDoc toString() {
2546        StringWriter writer = new StringWriter();
2547        writer.write(getSessionTypeString() + "(" + Helper.cr() + "\t" + getAccessor() + Helper.cr() + "\t" + getDatasourcePlatform() + ")");
2548        return writer.toString();
2549    }
2550
2551    /**
2552     * INTERNAL:
2553     * Unwrap the object if required.
2554     * This is used for the wrapper policy support and EJB.
2555     */

2556    public Object JavaDoc unwrapObject(Object JavaDoc proxy) {
2557        return getDescriptor(proxy).getObjectBuilder().unwrapObject(proxy, this);
2558    }
2559
2560    /**
2561     * PUBLIC:
2562     * Update the object and all of its privately owned parts in the database.
2563     * Update should only be used if the application knows that the object is new,
2564     * otherwise writeObject should be used.
2565     * The update operation can be customized through using an update query.
2566     *
2567     * @exception DatabaseException if an error occurs on the database,
2568     * these include constraint violations, security violations and general database erros.
2569     * @exception OptimisticLockException if the object's descriptor is using optimistic locking and
2570     * the object has been updated or deleted by another user since it was last read.
2571     *
2572     * @see UpdateObjectQuery
2573     * @see #writeObject(Object)
2574     */

2575    public Object JavaDoc updateObject(Object JavaDoc domainObject) throws DatabaseException, OptimisticLockException {
2576        UpdateObjectQuery query = new UpdateObjectQuery();
2577        query.setObject(domainObject);
2578        return executeQuery(query);
2579    }
2580
2581    /**
2582     * INTERNAL:
2583     * This method will be used to update the query with any settings required
2584     * For this session. It can also be used to validate execution.
2585     */

2586    public void validateQuery(DatabaseQuery query) {
2587        // a no-op for this class
2588
}
2589
2590    /**
2591     * TESTING:
2592     * This is used by testing code to ensure that a deletion was successful.
2593     */

2594    public boolean verifyDelete(Object JavaDoc domainObject) {
2595        ObjectBuilder builder = getDescriptor(domainObject).getObjectBuilder();
2596        Object JavaDoc implementation = builder.unwrapObject(domainObject, this);
2597
2598        return builder.verifyDelete(implementation, this);
2599    }
2600
2601    /**
2602     * INTERNAL:
2603     * Return if a JTS transaction was started by the session.
2604     * The session will start a JTS transaction if a unit of work or transaction is begun without a JTS transaction present.
2605     */

2606    public boolean wasJTSTransactionInternallyStarted() {
2607        return wasJTSTransactionInternallyStarted;
2608    }
2609
2610    /**
2611     * INTERNAL:
2612     * Wrap the object if required.
2613     * This is used for the wrapper policy support and EJB.
2614     */

2615    public Object JavaDoc wrapObject(Object JavaDoc implementation) {
2616        return getDescriptor(implementation).getObjectBuilder().wrapObject(implementation, this);
2617    }
2618
2619    /**
2620     * INTERNAL:
2621     * Write all of the objects and all of their privately owned parts in the database.
2622     * The allows for a group of new objects to be commited as a unit.
2623     * The objects will be commited through a single transactions and any
2624     * foreign keys/circular references between the objects will be resolved.
2625     */

2626    protected void writeAllObjects(IdentityHashtable domainObjects) throws DatabaseException, OptimisticLockException {
2627        getCommitManager().commitAllObjects(domainObjects);
2628    }
2629
2630    /**
2631     * INTERNAL:
2632     * Write all of the objects and all of their privately owned parts in the database.
2633     * The allows for a group of new objects to be commited as a unit.
2634     * The objects will be commited through a single transactions and any
2635     * foreign keys/circular references between the objects will be resolved.
2636     */

2637    protected void writeAllObjectsWithChangeSet(UnitOfWorkChangeSet uowChangeSet) throws DatabaseException, OptimisticLockException {
2638        getCommitManager().commitAllObjectsWithChangeSet(uowChangeSet);
2639    }
2640
2641    /**
2642     * PUBLIC:
2643     * Write the object and all of its privately owned parts in the database.
2644     * Write will determine if an insert or an update should be done,
2645     * it may go to the database to determine this (by default will check the identity map).
2646     * The write operation can be customized through using an write query.
2647     *
2648     * @exception DatabaseException if an error occurs on the database,
2649     * these include constraint violations, security violations and general database erros.
2650     * @exception OptimisticLockException if the object's descriptor is using optimistic locking and
2651     * the object has been updated or deleted by another user since it was last read.
2652     *
2653     * @see WriteObjectQuery
2654     * @see #insertObject(Object)
2655     * @see #updateObject(Object)
2656     */

2657    public Object JavaDoc writeObject(Object JavaDoc domainObject) throws DatabaseException, OptimisticLockException {
2658        WriteObjectQuery query = new WriteObjectQuery();
2659        query.setObject(domainObject);
2660        return executeQuery(query);
2661    }
2662
2663    /**
2664     * INTERNAL:
2665     * This method notifies the accessor that a particular sets of writes has
2666     * completed. This notification can be used for such thing as flushing the
2667     * batch mechanism
2668     */

2669    public void writesCompleted() {
2670        getAccessor().writesCompleted(this);
2671    }
2672
2673    /**
2674     * PUBLIC:
2675     * <p>
2676     * Return the log level
2677     * </p><p>
2678     *
2679     * @return the log level
2680     * </p><p>
2681     * @param category the string representation of a TopLink category, e.g. "sql", "transaction" ...
2682     * </p>
2683     */

2684    public int getLogLevel(String JavaDoc category) {
2685        return getSessionLog().getLevel(category);
2686    }
2687
2688    /**
2689     * PUBLIC:
2690     * <p>
2691     * Return the log level
2692     * </p><p>
2693     * @return the log level
2694     * </p>
2695     */

2696    public int getLogLevel() {
2697        return getSessionLog().getLevel();
2698    }
2699
2700    /**
2701     * PUBLIC:
2702     * <p>
2703     * Set the log level
2704     * </p><p>
2705     *
2706     * @param level the new log level
2707     * </p>
2708     */

2709    public void setLogLevel(int level) {
2710        getSessionLog().setLevel(level);
2711    }
2712
2713    /**
2714     * PUBLIC:
2715     * <p>
2716     * Check if a message of the given level would actually be logged.
2717     * </p><p>
2718     *
2719     * @return true if the given message level will be logged
2720     * </p><p>
2721     * @param level the log request level
2722     * @param category the string representation of a TopLink category
2723     * </p>
2724     */

2725    public boolean shouldLog(int Level, String JavaDoc category) {
2726        return getSessionLog().shouldLog(Level, category);
2727    }
2728
2729    /**
2730     * PUBLIC:
2731     * <p>
2732     * Log a message with level and category that needs to be translated.
2733     * </p><p>
2734     *
2735     * @param level the log request level value
2736     * </p><p>
2737     * @param message the string message
2738     * </p><p>
2739     * @param category the string representation of a TopLink category.
2740     * </p>
2741     */

2742    public void log(int level, String JavaDoc category, String JavaDoc message) {
2743        if (!shouldLog(level, category)) {
2744            return;
2745        }
2746        log(level, category, message, (Object JavaDoc[])null);
2747    }
2748
2749    /**
2750     * INTERNAL:
2751     * <p>
2752     * Log a message with level, category and a parameter that needs to be translated.
2753     * </p><p>
2754     *
2755     * @param level the log request level value
2756     * </p><p>
2757     * @param message the string message
2758     * </p><p>
2759     * @param category the string representation of a TopLink category.
2760     * </p><p>
2761     * @param param a parameter of the message
2762     * </p>
2763     */

2764    public void log(int level, String JavaDoc category, String JavaDoc message, Object JavaDoc param) {
2765        if (!shouldLog(level, category)) {
2766            return;
2767        }
2768        log(level, category, message, new Object JavaDoc[] { param });
2769    }
2770
2771    /**
2772     * INTERNAL:
2773     * <p>
2774     * Log a message with level, category and two parameters that needs to be translated.
2775     * </p><p>
2776     *
2777     * @param level the log request level value
2778     * </p><p>
2779     * @param message the string message
2780     * </p><p>
2781     * @param category the string representation of a TopLink category.
2782     * </p><p>
2783     * @param param1 a parameter of the message
2784     * </p><p>
2785     * @param param2 second parameter of the message
2786     * </p>
2787     */

2788    public void log(int level, String JavaDoc category, String JavaDoc message, Object JavaDoc param1, Object JavaDoc param2) {
2789        if (!shouldLog(level, category)) {
2790            return;
2791        }
2792        log(level, category, message, new Object JavaDoc[] { param1, param2 });
2793    }
2794
2795    /**
2796     * INTERNAL:
2797     * <p>
2798     * Log a message with level, category and three parameters that needs to be translated.
2799     * </p><p>
2800     *
2801     * @param level the log request level value
2802     * </p><p>
2803     * @param message the string message
2804     * </p><p>
2805     * @param category the string representation of a TopLink category.
2806     * </p><p>
2807     * @param param1 a parameter of the message
2808     * </p><p>
2809     * @param param2 second parameter of the message
2810     * </p><p>
2811     * @param param3 third parameter of the message
2812     * </p>
2813     */

2814    public void log(int level, String JavaDoc category, String JavaDoc message, Object JavaDoc param1, Object JavaDoc param2, Object JavaDoc param3) {
2815        if (!shouldLog(level, category)) {
2816            return;
2817        }
2818        log(level, category, message, new Object JavaDoc[] { param1, param2, param3 });
2819    }
2820
2821    /**
2822     * INTERNAL:
2823     * <p>
2824     * Log a message with level, category and an array of parameters that needs to be translated.
2825     * </p><p>
2826     *
2827     * @param level the log request level value
2828     * </p><p>
2829     * @param message the string message
2830     * </p><p>
2831     * @param category the string representation of a TopLink category.
2832     * </p><p>
2833     * @param params array of parameters to the message
2834     * </p>
2835     */

2836    public void log(int level, String JavaDoc category, String JavaDoc message, Object JavaDoc[] params) {
2837        log(level, category, message, params, null);
2838    }
2839
2840    /**
2841     * INTERNAL:
2842     * <p>
2843     * Log a message with level, category, parameters and accessor that needs to be translated.
2844     * </p><p>
2845     *
2846     * @param level the log request level value
2847     * </p><p>
2848     * @param message the string message
2849     * </p><p>
2850     * @param params array of parameters to the message
2851     * </p><p>
2852     * @param accessor the connection that generated the log entry
2853     * </p><p>
2854     * @param category the string representation of a TopLink category.
2855     * </p>
2856     */

2857    public void log(int level, String JavaDoc category, String JavaDoc message, Object JavaDoc[] params, Accessor accessor) {
2858        log(level, category, message, params, accessor, true);
2859    }
2860
2861    /**
2862     * INTERNAL:
2863     * <p>
2864     * Log a message with level, category, parameters and accessor. shouldTranslate determines if the message needs to be translated.
2865     * </p><p>
2866     *
2867     * @param level the log request level value
2868     * </p><p>
2869     * @param message the string message
2870     * </p><p>
2871     * @param params array of parameters to the message
2872     * </p><p>
2873     * @param accessor the connection that generated the log entry
2874     * </p><p>
2875     * @param category the string representation of a TopLink category.
2876     * </p><p>
2877     * @param shouldTranslate true if the message needs to be translated.
2878     * </p>
2879     */

2880    public void log(int level, String JavaDoc category, String JavaDoc message, Object JavaDoc[] params, Accessor accessor, boolean shouldTranslate) {
2881        if (shouldLog(level, category)) {
2882            startOperationProfile(SessionProfiler.Logging);
2883            log(new SessionLogEntry(level, category, this, message, params, accessor, shouldTranslate));
2884            endOperationProfile(SessionProfiler.Logging);
2885        }
2886    }
2887
2888    /**
2889     * INTERNAL:
2890     * <p>
2891     * Log a message with level, parameters and accessor that needs to be translated.
2892     * </p><p>
2893     *
2894     * @param level the log request level value
2895     * </p><p>
2896     * @param message the string message
2897     * </p><p>
2898     * @param params array of parameters to the message
2899     * </p><p>
2900     * @param accessor the connection that generated the log entry
2901     * </p>
2902     */

2903    public void log(int level, String JavaDoc message, Object JavaDoc[] params, Accessor accessor) {
2904        log(level, message, params, accessor, true);
2905    }
2906
2907    /**
2908     * INTERNAL:
2909     * <p>
2910     * Log a message with level, parameters and accessor. shouldTranslate determines if the message needs to be translated.
2911     * </p><p>
2912     *
2913     * @param level the log request level value
2914     * </p><p>
2915     * @param message the string message
2916     * </p><p>
2917     * @param params array of parameters to the message
2918     * </p><p>
2919     * @param accessor the connection that generated the log entry
2920     * </p><p>
2921     * @param shouldTranslate true if the message needs to be translated.
2922     * </p>
2923     */

2924    public void log(int level, String JavaDoc message, Object JavaDoc[] params, Accessor accessor, boolean shouldTranslate) {
2925        if (shouldLog(level, null)) {
2926            startOperationProfile(SessionProfiler.Logging);
2927            log(new SessionLogEntry(level, this, message, params, accessor, shouldTranslate));
2928            endOperationProfile(SessionProfiler.Logging);
2929        }
2930    }
2931
2932    /**
2933     * PUBLIC:
2934     * <p>
2935     * Log a throwable with level and category.
2936     * </p><p>
2937     *
2938     * @param level the log request level value
2939     * </p><p>
2940     * @param category the string representation of a TopLink category.
2941     * </p><p>
2942     * @param throwable a Throwable
2943     * </p>
2944     */

2945    public void logThrowable(int level, String JavaDoc category, Throwable JavaDoc throwable) {
2946        // Must not create the log if not logging as is a performance issue.
2947
if (shouldLog(level, category)) {
2948            startOperationProfile(SessionProfiler.Logging);
2949            log(new SessionLogEntry(this, level, category, throwable));
2950            endOperationProfile(SessionProfiler.Logging);
2951        }
2952    }
2953
2954    /**
2955     * PUBLIC:
2956     * <p>
2957     * This method is called when a severe level message needs to be logged.
2958     * The message will be translated
2959     * </p><p>
2960     *
2961     * @param message the message key
2962     * </p>
2963     */

2964    public void severe(String JavaDoc message, String JavaDoc category) {
2965        log(SessionLog.SEVERE, category, message);
2966    }
2967
2968    /**
2969     * PUBLIC:
2970     * <p>
2971     * This method is called when a warning level message needs to be logged.
2972     * The message will be translated
2973     * </p><p>
2974     *
2975     * @param message the message key
2976     * </p>
2977     */

2978    public void warning(String JavaDoc message, String JavaDoc category) {
2979        log(SessionLog.WARNING, category, message);
2980    }
2981
2982    /**
2983     * PUBLIC:
2984     * <p>
2985     * This method is called when a info level message needs to be logged.
2986     * The message will be translated
2987     * </p><p>
2988     *
2989     * @param message the message key
2990     * </p>
2991     */

2992    public void info(String JavaDoc message, String JavaDoc category) {
2993        log(SessionLog.INFO, category, message);
2994    }
2995
2996    /**
2997     * PUBLIC:
2998     * <p>
2999     * This method is called when a config level message needs to be logged.
3000     * The message will be translated
3001     * </p><p>
3002     *
3003     * @param message the message key
3004     * </p>
3005     */

3006    public void config(String JavaDoc message, String JavaDoc category) {
3007        log(SessionLog.CONFIG, category, message);
3008    }
3009
3010    /**
3011     * PUBLIC:
3012     * <p>
3013     * This method is called when a fine level message needs to be logged.
3014     * The message will be translated
3015     * </p><p>
3016     *
3017     * @param message the message key
3018     * </p>
3019     */

3020    public void fine(String JavaDoc message, String JavaDoc category) {
3021        log(SessionLog.FINE, category, message);
3022    }
3023
3024    /**
3025     * PUBLIC:
3026     * <p>
3027     * This method is called when a finer level message needs to be logged.
3028     * The message will be translated
3029     * </p><p>
3030     *
3031     * @param message the message key
3032     * </p>
3033     */

3034    public void finer(String JavaDoc message, String JavaDoc category) {
3035        log(SessionLog.FINER, category, message);
3036    }
3037
3038    /**
3039     * PUBLIC:
3040     * <p>
3041     * This method is called when a finest level message needs to be logged.
3042     * The message will be translated
3043     * </p><p>
3044     *
3045     * @param message the message key
3046     * </p>
3047     */

3048    public void finest(String JavaDoc message, String JavaDoc category) {
3049        log(SessionLog.FINEST, category, message);
3050    }
3051
3052    /**
3053     * PUBLIC:
3054     * Allow any SEVERE level exceptions that occur within TopLink to be logged and handled by the exception handler.
3055     */

3056    public Object JavaDoc handleSevere(RuntimeException JavaDoc exception) throws RuntimeException JavaDoc {
3057        logThrowable(SessionLog.SEVERE, null, exception);
3058        if (hasExceptionHandler()) {
3059            return getExceptionHandler().handleException(exception);
3060        } else {
3061            throw exception;
3062        }
3063    }
3064}
3065
Popular Tags