All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oracle.toplink.essentials.internal.sessions.AbstractSession Maven / Gradle / Ivy

There is a newer version: 2.1-60f
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * // Copyright (c) 1998, 2007, Oracle. All rights reserved.
 * 
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package oracle.toplink.essentials.internal.sessions;

import java.util.*;
import java.io.*;
import oracle.toplink.essentials.descriptors.ClassDescriptor;
import oracle.toplink.essentials.internal.helper.*;
import oracle.toplink.essentials.platform.server.ServerPlatform;
import oracle.toplink.essentials.queryframework.*;
import oracle.toplink.essentials.expressions.*;
import oracle.toplink.essentials.internal.identitymaps.*;
import oracle.toplink.essentials.internal.descriptors.*;
import oracle.toplink.essentials.internal.databaseaccess.*;
import oracle.toplink.essentials.exceptions.*;
import oracle.toplink.essentials.sessions.*;
import oracle.toplink.essentials.internal.sequencing.Sequencing;
import oracle.toplink.essentials.logging.*;
import oracle.toplink.essentials.internal.sessions.AbstractRecord;
import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
import oracle.toplink.essentials.internal.helper.ConcurrencyManager;
import oracle.toplink.essentials.internal.helper.IdentityHashtable;

/**
 * Implementation of oracle.toplink.essentials.sessions.Session
 * The public interface should be used by public API and testing, the implementation should be used internally.
 * @see oracle.toplink.essentials.sessions.Session
 *
 * 

* Purpose: Define the interface and common protocol of a TopLink compliant session. *

* Description: The session is the primary interface into TopLink, * the application should do all of its reading and writing of objects through the session. * The session also manages transactions and units of work. Normally the session * is passed and used by the application controler objects. Controler objects normally * sit behind the GUI and perform the buiness processes required for the application, * they should perform all explict database access and database access should be avoided from * the domain object model. Do not use a globally accessable session instance, doing so does * not allow for multiple sessions. Multiple sessions may required when performing things like * data migration or multiple database access, as well the unit of work feature requires the usage * of multiple session instances. Although session is abstract, any users of its subclasses * should only cast the variables to Session to allow usage of any of its subclasses. *

* Responsibilities: *

    *
  • Connecting/disconnecting. *
  • Reading and writing objects. *
  • Transaction and unit of work support. *
  • Identity maps and caching. *
* @see DatabaseSession */ public abstract class AbstractSession implements oracle.toplink.essentials.sessions.Session, java.io.Serializable, java.lang.Cloneable { /** ExceptionHandler handles database exceptions. */ transient protected ExceptionHandler exceptionHandler; /** IntegrityChecker catch all the descriptor Exceptions. */ transient protected IntegrityChecker integrityChecker; /** The project stores configuration information, such as the descriptors and login. */ transient protected oracle.toplink.essentials.sessions.Project project; /** Ensure mutual exclusion of the session's transaction state across multiple threads.*/ transient protected ConcurrencyManager transactionMutex; /** Manages the live object cache.*/ protected oracle.toplink.essentials.internal.sessions.IdentityMapAccessor identityMapAccessor; /** If Transactions were externally started */ protected boolean wasJTSTransactionInternallyStarted; /** The connection to the data store. */ transient protected Accessor accessor; /** Allow the datasource platform to be cached. */ transient protected Platform platform; /** Stores predefine reusable queries.*/ transient protected Map queries; /** Stores predefined not yet parsed EJBQL queries.*/ transient protected List ejbqlPlaceHolderQueries; /** Resolves referencial integrity on commits. */ transient protected CommitManager commitManager; /** Tool that log performance information. */ transient protected SessionProfiler profiler; /** Support being owned by a session broker. */ transient protected AbstractSession broker; /** Used to identify a session when using the session broker. */ protected String name; /** Keep track of active units of work. */ transient protected int numberOfActiveUnitsOfWork; /** Destination for logged messages and SQL. */ transient protected SessionLog sessionLog; /** When logging the name of the session is typed: class name + system hashcode. */ transient protected String logSessionString; /** Stores the event listeners for this session. */ transient protected SessionEventManager eventManager; /** Allow for user defined properties. */ protected Map properties; /** Delegate that handles synchronizing a UnitOfWork with an external transaction. */ transient protected ExternalTransactionController externalTransactionController; /** Last descriptor accessed, use to optimize descriptor lookup. */ transient protected ClassDescriptor lastDescriptorAccessed; /** Used to determine If a session is in a profile or not */ public boolean isInProfile; /** * INTERNAL: * Create and return a new session. * This should only be called if the database login information is not know at the time of creation. * Normally it is better to call the constructor that takes the login information as an argument * so that the session can initialize itself to the platform information given in the login. */ protected AbstractSession() { this.name = ""; initializeIdentityMapAccessor(); // PERF - move to lazy init (3286091) this.numberOfActiveUnitsOfWork = 0; } /** * INTERNAL: * Create a blank session, used for proxy session. */ protected AbstractSession(int nothing) { } /** * PUBLIC: * Create and return a new session. * By giving the login information on creation this allows the session to initialize itself * to the platform given in the login. This constructor does not return a connected session. * To connect the session to the database login() must be sent to it. The login(userName, password) * method may also be used to connect the session, this allows for the user name and password * to be given at login but for the other database information to be provided when the session is created. */ public AbstractSession(Login login) { this(new oracle.toplink.essentials.sessions.Project(login)); } /** * PUBLIC: * Create and return a new session. * This constructor does not return a connected session. * To connect the session to the database login() must be sent to it. The login(userName, password) * method may also be used to connect the session, this allows for the user name and password * to be given at login but for the other database information to be provided when the session is created. */ public AbstractSession(oracle.toplink.essentials.sessions.Project project) { this(); this.project = project; if (project.getDatasourceLogin() == null) { throw ValidationException.projectLoginIsNull(this); } } /** * INTERNAL: * Called by a sessions queries to obtain individual query ids. * CR #2698903 */ public long getNextQueryId() { return QueryCounter.getCount(); } /** * INTERNAL: * Return a unit of work for this session not registered with the JTS transaction. */ public UnitOfWorkImpl acquireNonSynchronizedUnitOfWork() { setNumberOfActiveUnitsOfWork(getNumberOfActiveUnitsOfWork() + 1); UnitOfWorkImpl unitOfWork = new UnitOfWorkImpl(this); if (shouldLog(SessionLog.FINER, SessionLog.TRANSACTION)) { log(SessionLog.FINER, SessionLog.TRANSACTION, "acquire_unit_of_work_with_argument", String.valueOf(System.identityHashCode(unitOfWork))); } return unitOfWork; } /** * PUBLIC: * Return a unit of work for this session. * The unit of work is an object level transaction that allows * a group of changes to be applied as a unit. * * @see UnitOfWork */ public UnitOfWork acquireUnitOfWork() { UnitOfWorkImpl unitOfWork = acquireNonSynchronizedUnitOfWork(); unitOfWork.registerWithTransactionIfRequired(); return unitOfWork; } /** * PUBLIC: * Add an alias for the descriptor */ public void addAlias(String alias, ClassDescriptor descriptor) { project.addAlias(alias, descriptor); } /** * PUBLIC: * Add the query to the session queries with the given name. * This allows for common queries to be pre-defined, reused and executed by name. */ public void addQuery(String name, DatabaseQuery query) { query.setName(name); addQuery(query); } /** * INTERNAL: * Return all pre-defined not yet parsed EJBQL queries. * @see #getAllQueries() */ public void addEjbqlPlaceHolderQuery(DatabaseQuery query) { getEjbqlPlaceHolderQueries().add(query); } /** * INTERNAL: * Add the query to the session queries. */ protected void addQuery(DatabaseQuery query) { Vector queriesByName = (Vector)getQueries().get(query.getName()); if (queriesByName == null) { // lazily create Vector in Hashtable. queriesByName = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(); getQueries().put(query.getName(), queriesByName); } // Check that we do not already have a query that matched it for (Enumeration enumtr = queriesByName.elements(); enumtr.hasMoreElements();) { DatabaseQuery existingQuery = (DatabaseQuery)enumtr.nextElement(); if (Helper.areTypesAssignable(query.getArgumentTypes(), existingQuery.getArgumentTypes())) { throw ValidationException.existingQueryTypeConflict(query, existingQuery); } } queriesByName.add(query); } /** * INTERNAL: * Called by beginTransaction() to start a transaction. * This starts a real database transaction. */ protected void basicBeginTransaction() throws DatabaseException { try { getAccessor().beginTransaction(this); } catch (RuntimeException exception) { handleException(exception); } } /** * INTERNAL: * Called after transaction is completed (committed or rolled back) */ public void afterTransaction(boolean committed, boolean isExternalTransaction) { } /** * INTERNAL: * Called by commitTransaction() to commit a transaction. * This commits the active transaction. */ protected void basicCommitTransaction() throws DatabaseException { try { getAccessor().commitTransaction(this); } catch (RuntimeException exception) { handleException(exception); } } /** * INTERNAL: * Called by rollbackTransaction() to rollback a transaction. * This rollsback the active transaction. */ protected void basicRollbackTransaction() throws DatabaseException { try { getAccessor().rollbackTransaction(this); } catch (RuntimeException exception) { handleException(exception); } } /** * INTERNAL: * Attempts to begin an external transaction. * Returns true only in one case - * extenal transaction has been internally started during this method call: * wasJTSTransactionInternallyStarted()==false in the beginning of this method and * wasJTSTransactionInternallyStarted()==true in the end of this method. */ public boolean beginExternalTransaction() { boolean externalTransactionHasBegun = false; if (hasExternalTransactionController() && !wasJTSTransactionInternallyStarted()) { try { getExternalTransactionController().beginTransaction(this); } catch (RuntimeException exception) { handleException(exception); } if (wasJTSTransactionInternallyStarted()) { externalTransactionHasBegun = true; log(SessionLog.FINER, SessionLog.TRANSACTION, "external_transaction_has_begun_internally"); } } return externalTransactionHasBegun; } /** * PUBLIC: * Begin a transaction on the database. * This allows a group of database modification to be commited or rolledback as a unit. * All writes/deletes will be sent to the database be will not be visible to other users until commit. * Although databases do not allow nested transaction, * TopLink supports nesting through only committing to the database on the outer commit. * * @exception DatabaseException if the database connection is lost or the begin is rejected. * @exception ConcurrencyException if this session's transaction is aquired by another thread and a timeout occurs. * * @see #isInTransaction() */ public void beginTransaction() throws DatabaseException, ConcurrencyException { // If there is no db transaction in progress // beginExternalTransaction() starts an external transaction - // provided externalTransactionController is used, and there is // no active external transaction - so we have to start one internally. if (!isInTransaction()) { beginExternalTransaction(); } // For unit of work and client session multi threading is allowed as they are a context, // this is required for JTS/RMI/CORBA/EJB stuff where the server thread can be different across calls. if (isUnitOfWork() || isClientSession()) { getTransactionMutex().setActiveThread(Thread.currentThread()); } // Ensure mutual exclusion and call subclass specific begin. getTransactionMutex().acquire(); if (!getTransactionMutex().isNested()) { getEventManager().preBeginTransaction(); basicBeginTransaction(); getEventManager().postBeginTransaction(); } } /** * PUBLIC: * clear the integrityChecker. IntegrityChecker holds all the Descriptor Exceptions. */ public void clearIntegrityChecker() { setIntegrityChecker(null); } /** * INTERNAL: * clear the lastDescriptorAccessed. */ public void clearLastDescriptorAccessed() { lastDescriptorAccessed = null; } /** * PUBLIC: * Clear the profiler, this will end the current profile opperation. */ public void clearProfile() { setProfiler(null); } /** * INTERNAL: * Clones the descriptor */ public Object clone() { // An alternative to this process should be found try { return super.clone(); } catch (Exception exception) { return null; } } /** * INTERNAL: * Attempts to commit the running internally started external transaction. * Returns true only in one case - * extenal transaction has been internally committed during this method call: * wasJTSTransactionInternallyStarted()==true in the beginning of this method and * wasJTSTransactionInternallyStarted()==false in the end of this method. */ public boolean commitExternalTransaction() { boolean externalTransactionHasCommitted = false; if (hasExternalTransactionController() && wasJTSTransactionInternallyStarted()) { try { getExternalTransactionController().commitTransaction(this); } catch (RuntimeException exception) { handleException(exception); } if (!wasJTSTransactionInternallyStarted()) { externalTransactionHasCommitted = true; log(SessionLog.FINER, SessionLog.TRANSACTION, "external_transaction_has_committed_internally"); } } return externalTransactionHasCommitted; } /** * PUBLIC: * Commit the active database transaction. * This allows a group of database modification to be commited or rolledback as a unit. * All writes/deletes will be sent to the database be will not be visible to other users until commit. * Although databases do not allow nested transaction, * TopLink supports nesting through only committing to the database on the outer commit. * * @exception DatabaseException most databases validate changes as they are done, * normally errors do not occur on commit unless the disk fails or the connection is lost. * @exception ConcurrencyException if this session is not within a transaction. */ public void commitTransaction() throws DatabaseException, ConcurrencyException { // Release mutex and call subclass specific commit. if (!getTransactionMutex().isNested()) { getEventManager().preCommitTransaction(); basicCommitTransaction(); getEventManager().postCommitTransaction(); } // This MUST not be in a try catch or finally as if the commit failed the transaction is still open. getTransactionMutex().release(); // If there is no db transaction in progress // if there is an active external transaction // which was started internally - it should be committed internally, too. if (!isInTransaction()) { commitExternalTransaction(); } } /** * INTERNAL: * Return if the two object match completely. * This checks the objects attributes and their private parts. */ public boolean compareObjects(Object firstObject, Object secondObject) { if ((firstObject == null) && (secondObject == null)) { return true; } if ((firstObject == null) || (secondObject == null)) { return false; } if (!(firstObject.getClass().equals(secondObject.getClass()))) { return false; } ObjectBuilder builder = getDescriptor(firstObject.getClass()).getObjectBuilder(); return builder.compareObjects(builder.unwrapObject(firstObject, this), builder.unwrapObject(secondObject, this), this); } /** * TESTING: * Return true if the object do not match. * This checks the objects attributes and their private parts. */ public boolean compareObjectsDontMatch(Object firstObject, Object secondObject) { return !this.compareObjects(firstObject, secondObject); } /** * PUBLIC: * Return true if the pre-defined query is defined on the session. */ public boolean containsQuery(String queryName) { return getQueries().containsKey(queryName); } /** * PUBLIC: * Return a complete copy of the object. * This can be used to obtain a scatch copy of an object, * or for templatizing an existing object into another new object. * The object and all of its privately owned parts will be copied, the object's primary key will be reset to null. * * @see #copyObject(Object, ObjectCopyingPolicy) */ public Object copyObject(Object original) { return copyObject(original, new ObjectCopyingPolicy()); } /** * PUBLIC: * Return a complete copy of the object. * This can be used to obtain a scatch copy of an object, * or for templatizing an existing object into another new object. * The object copying policy allow for the depth, and reseting of the primary key to null, to be specified. */ public Object copyObject(Object original, ObjectCopyingPolicy policy) { if (original == null) { return null; } ClassDescriptor descriptor = getDescriptor(original); if (descriptor == null) { return original; } policy.setSession(this); return descriptor.getObjectBuilder().copyObject(original, policy); } /** * INTERNAL: * Copy the read only classes from the unit of work * * Added Nov 8, 2000 JED for Patch 2.5.1.8 * Ref: Prs 24502 */ public Vector copyReadOnlyClasses() { return getDefaultReadOnlyClasses(); } /** * PUBLIC: * delete all of the objects and all of their privately owned parts in the database. * The allows for a group of objects to be deleted as a unit. * The objects will be deleted through a single transactions. * * @exception DatabaseException if an error occurs on the database, * these include constraint violations, security violations and general database erros. * @exception OptimisticLockException if the object's descriptor is using optimistic locking and * the object has been updated or deleted by another user since it was last read. */ public void deleteAllObjects(Collection domainObjects) throws DatabaseException, OptimisticLockException { for (Iterator objectsEnum = domainObjects.iterator(); objectsEnum.hasNext();) { deleteObject(objectsEnum.next()); } } /** * PUBLIC: * delete all of the objects and all of their privately owned parts in the database. * The allows for a group of objects to be deleted as a unit. * The objects will be deleted through a single transactions. * * @exception DatabaseException if an error occurs on the database, * these include constraint violations, security violations and general database erros. * @exception OptimisticLockException if the object's descriptor is using optimistic locking and * the object has been updated or deleted by another user since it was last read. */ public void deleteAllObjects(Vector domainObjects) throws DatabaseException, OptimisticLockException { for (Enumeration objectsEnum = domainObjects.elements(); objectsEnum.hasMoreElements();) { deleteObject(objectsEnum.nextElement()); } } /** * PUBLIC: * Delete the object and all of its privately owned parts from the database. * The delete operation can be customized through using a delete query. * * @exception DatabaseException if an error occurs on the database, * these include constraint violations, security violations and general database erros. * An database error is not raised if the object is already deleted or no rows are effected. * @exception OptimisticLockException if the object's descriptor is using optimistic locking and * the object has been updated or deleted by another user since it was last read. * * @see DeleteObjectQuery */ public Object deleteObject(Object domainObject) throws DatabaseException, OptimisticLockException { DeleteObjectQuery query = new DeleteObjectQuery(); query.setObject(domainObject); return executeQuery(query); } /** * PUBLIC: * Return if the object exists on the database or not. * This always checks existence on the database. */ public boolean doesObjectExist(Object object) throws DatabaseException { DoesExistQuery query = new DoesExistQuery(); query.setObject(object); query.checkDatabaseForDoesExist(); return ((Boolean)executeQuery(query)).booleanValue(); } /** * PUBLIC: * Turn off logging */ public void dontLogMessages() { setLogLevel(SessionLog.OFF); } /** * INTERNAL: * End the operation timing. */ public void endOperationProfile(String operationName) { if (isInProfile()) { getProfiler().endOperationProfile(operationName); } } /** * INTERNAL: * Updates the value of SessionProfiler state */ public void updateProfile(String operationName, Object value) { if (isInProfile()) { getProfiler().update(operationName, value); } } /** * INTERNAL: * Updates the count of SessionProfiler event */ public void incrementProfile(String operationName) { if (isInProfile()) { getProfiler().occurred(operationName); } } /** * INTERNAL: * Overridden by subclasses that do more than just execute the call. * Executes the call directly on this session and does not check which * session it should have executed on. */ public Object executeCall(Call call, AbstractRecord translationRow, DatabaseQuery query) throws DatabaseException { //** sequencing refactoring if (query.getAccessor() == null) { query.setAccessor(getAccessor()); } try { return query.getAccessor().executeCall(call, translationRow, this); } finally { if (call.isFinished()) { query.setAccessor(null); } } } /** * PUBLIC: * Execute the call on the database. * The row count is returned. * The call can be a stored procedure call, SQL call or other type of call. *

Example: *

session.executeNonSelectingCall(new SQLCall("Delete from Employee"); * * @see #executeSelectingCall(Call) */ public int executeNonSelectingCall(Call call) throws DatabaseException { DataModifyQuery query = new DataModifyQuery(); query.setCall(call); Integer value = (Integer)executeQuery(query); if (value == null) { return 0; } else { return value.intValue(); } } /** * PUBLIC: * Execute the sql on the database. *

Example: *

session.executeNonSelectingSQL("Delete from Employee"); * @see #executeNonSelectingCall(Call) */ public void executeNonSelectingSQL(String sqlString) throws DatabaseException { executeNonSelectingCall(new SQLCall(sqlString)); } /** * PUBLIC: * Execute the pre-defined query by name and return the result. * Queries can be pre-defined and named to allow for their reuse. * * @see #addQuery(String, DatabaseQuery) */ public Object executeQuery(String queryName) throws DatabaseException { DatabaseQuery query = getQuery(queryName); if (query == null) { throw QueryException.queryNotDefined(queryName); } return executeQuery(query); } /** * PUBLIC: * Execute the pre-defined query by name and return the result. * Queries can be pre-defined and named to allow for their reuse. * The class is the descriptor in which the query was pre-defined. * * @see DescriptorQueryManager#addQuery(String, DatabaseQuery) */ public Object executeQuery(String queryName, Class domainClass) throws DatabaseException { ClassDescriptor descriptor = getDescriptor(domainClass); if (descriptor == null) { throw QueryException.descriptorIsMissingForNamedQuery(domainClass, queryName); } DatabaseQuery query = (DatabaseQuery)descriptor.getQueryManager().getQuery(queryName); if (query == null) { throw QueryException.queryNotDefined(queryName, domainClass); } return executeQuery(query); } /** * PUBLIC: * Execute the pre-defined query by name and return the result. * Queries can be pre-defined and named to allow for their reuse. * The class is the descriptor in which the query was pre-defined. * * @see DescriptorQueryManager#addQuery(String, DatabaseQuery) */ public Object executeQuery(String queryName, Class domainClass, Object arg1) throws DatabaseException { Vector argumentValues = new Vector(); argumentValues.addElement(arg1); return executeQuery(queryName, domainClass, argumentValues); } /** * PUBLIC: * Execute the pre-defined query by name and return the result. * Queries can be pre-defined and named to allow for their reuse. * The class is the descriptor in which the query was pre-defined. * * @see DescriptorQueryManager#addQuery(String, DatabaseQuery) */ public Object executeQuery(String queryName, Class domainClass, Object arg1, Object arg2) throws DatabaseException { Vector argumentValues = new Vector(); argumentValues.addElement(arg1); argumentValues.addElement(arg2); return executeQuery(queryName, domainClass, argumentValues); } /** * PUBLIC: * Execute the pre-defined query by name and return the result. * Queries can be pre-defined and named to allow for their reuse. * The class is the descriptor in which the query was pre-defined. * * @see DescriptorQueryManager#addQuery(String, DatabaseQuery) */ public Object executeQuery(String queryName, Class domainClass, Object arg1, Object arg2, Object arg3) throws DatabaseException { Vector argumentValues = new Vector(); argumentValues.addElement(arg1); argumentValues.addElement(arg2); argumentValues.addElement(arg3); return executeQuery(queryName, domainClass, argumentValues); } /** * PUBLIC: * Execute the pre-defined query by name and return the result. * Queries can be pre-defined and named to allow for their reuse. * The class is the descriptor in which the query was pre-defined. * * @see DescriptorQueryManager#addQuery(String, DatabaseQuery) */ public Object executeQuery(String queryName, Class domainClass, Vector argumentValues) throws DatabaseException { ClassDescriptor descriptor = getDescriptor(domainClass); if (descriptor == null) { throw QueryException.descriptorIsMissingForNamedQuery(domainClass, queryName); } DatabaseQuery query = (DatabaseQuery)descriptor.getQueryManager().getQuery(queryName, argumentValues); if (query == null) { throw QueryException.queryNotDefined(queryName, domainClass); } return executeQuery(query, argumentValues); } /** * PUBLIC: * Execute the pre-defined query by name and return the result. * Queries can be pre-defined and named to allow for their reuse. * * @see #addQuery(String, DatabaseQuery) */ public Object executeQuery(String queryName, Object arg1) throws DatabaseException { Vector argumentValues = new Vector(); argumentValues.addElement(arg1); return executeQuery(queryName, argumentValues); } /** * PUBLIC: * Execute the pre-defined query by name and return the result. * Queries can be pre-defined and named to allow for their reuse. * * @see #addQuery(String, DatabaseQuery) */ public Object executeQuery(String queryName, Object arg1, Object arg2) throws DatabaseException { Vector argumentValues = new Vector(); argumentValues.addElement(arg1); argumentValues.addElement(arg2); return executeQuery(queryName, argumentValues); } /** * PUBLIC: * Execute the pre-defined query by name and return the result. * Queries can be pre-defined and named to allow for their reuse. * * @see #addQuery(String, DatabaseQuery) */ public Object executeQuery(String queryName, Object arg1, Object arg2, Object arg3) throws DatabaseException { Vector argumentValues = new Vector(); argumentValues.addElement(arg1); argumentValues.addElement(arg2); argumentValues.addElement(arg3); return executeQuery(queryName, argumentValues); } /** * PUBLIC: * Execute the pre-defined query by name and return the result. * Queries can be pre-defined and named to allow for their reuse. * * @see #addQuery(String, DatabaseQuery) */ public Object executeQuery(String queryName, Vector argumentValues) throws DatabaseException { DatabaseQuery query = getQuery(queryName, argumentValues); if (query == null) { throw QueryException.queryNotDefined(queryName); } return executeQuery(query, argumentValues); } /** * PUBLIC: * Execute the database query. * A query is a database operation such as reading or writting. * The query allows for the operation to be customized for such things as, * performance, depth, caching, etc. * * @see DatabaseQuery */ public Object executeQuery(DatabaseQuery query) throws DatabaseException { return executeQuery(query, new DatabaseRecord(1)); } /** * PUBLIC: * Return the results from exeucting the database query. * the arguments are passed in as a vector */ public Object executeQuery(DatabaseQuery query, Vector argumentValues) throws DatabaseException { if (query == null) { throw QueryException.queryNotDefined(); } AbstractRecord row = query.rowFromArguments(argumentValues); return executeQuery(query, row); } /** * INTERNAL: * Return the results from exeucting the database query. * the arguments should be a database row with raw data values. */ public Object executeQuery(DatabaseQuery query, AbstractRecord row) throws DatabaseException { if (hasBroker()) { if (!((query.isDataModifyQuery() || query.isDataReadQuery()) && (query.getSessionName() == null))) { return getBroker().executeQuery(query, row); } } if (query == null) { throw QueryException.queryNotDefined(); } //CR#2272 log(SessionLog.FINEST, SessionLog.QUERY, "execute_query", query); try { getEventManager().preExecuteQuery(query); Object result; if (isInProfile()) { result = getProfiler().profileExecutionOfQuery(query, row, this); } else { result = internalExecuteQuery(query, row); } getEventManager().postExecuteQuery(query, result); return result; } catch (RuntimeException exception) { if (exception instanceof QueryException) { QueryException queryException = (QueryException)exception; if (queryException.getQuery() == null) { queryException.setQuery(query); } if (queryException.getQueryArgumentsRecord() == null) { queryException.setQueryArguments(row); } if (queryException.getSession() == null) { queryException.setSession(this); } } else if (exception instanceof DatabaseException) { DatabaseException databaseException = (DatabaseException)exception; if (databaseException.getQuery() == null) { databaseException.setQuery(query); } if (databaseException.getQueryArgumentsRecord() == null) { databaseException.setQueryArguments(row); } if (databaseException.getSession() == null) { databaseException.setSession(this); } } return handleException(exception); } } /** * PUBLIC: * Execute the call on the database and return the result. * The call must return a value, if no value is return executeNonSelectCall must be used. * The call can be a stored procedure call, SQL call or other type of call. * A vector of database rows is returned, database row implements Java 2 Map which should be used to access the data. *

Example: *

session.executeSelectingCall(new SQLCall("Select * from Employee"); * * @see #executeNonSelectingCall(Call) */ public Vector executeSelectingCall(Call call) throws DatabaseException { DataReadQuery query = new DataReadQuery(); query.setCall(call); return (Vector)executeQuery(query); } /** * PUBLIC: * Execute the sql on the database and return the result. * It must return a value, if no value is return executeNonSelectingSQL must be used. * A vector of database rows is returned, database row implements Java 2 Map which should be used to access the data. *

Example: *

session.executeSelectingCall("Select * from Employee"); * * @see #executeSelectingCall(Call) */ public Vector executeSQL(String sqlString) throws DatabaseException { return executeSelectingCall(new SQLCall(sqlString)); } /** * INTERNAL: * Return the lowlevel database accessor. * The database accesor is used for direct database access. */ public synchronized Accessor getAccessor() { if ((accessor == null) && (project != null) && (project.getDatasourceLogin() != null)) { // PERF: lazy init, not always required. accessor = project.getDatasourceLogin().buildAccessor(); } return accessor; } /** * INTERNAL: * Return the lowlevel database accessor. * The database accesor is used for direct database access. * If sessionBroker is used, the right accessor for this * broker will be returned. */ public Accessor getAccessor(Class domainClass) { return getAccessor(); } /** * INTERNAL: * Return the lowlevel database accessor. * The database accesor is used for direct database access. * If sessionBroker is used, the right accessor for this * broker will be returned based on the session name. */ public Accessor getAccessor(String sessionName) { return getAccessor(); } /** * PUBLIC: * Return the active session for the current active external (JTS) transaction. * This should only be used with JTS and will return the session if no external transaction exists. */ public oracle.toplink.essentials.sessions.Session getActiveSession() { oracle.toplink.essentials.sessions.Session activeSession = getActiveUnitOfWork(); if (activeSession == null) { activeSession = this; } return activeSession; } /** * PUBLIC: * Return the active unit of work for the current active external (JTS) transaction. * This should only be used with JTS and will return null if no external transaction exists. */ public oracle.toplink.essentials.sessions.UnitOfWork getActiveUnitOfWork() { if (hasExternalTransactionController()) { return getExternalTransactionController().getActiveUnitOfWork(); } /* Steven Vo: CR# 2517 Get from the server session since the external transaction controller could be null out from the client session by TL WebLogic 5.1 to provide non-jts transaction operations */ if (isClientSession()) { return ((oracle.toplink.essentials.threetier.ClientSession)this).getParent().getActiveUnitOfWork(); } return null; } /** * INTERNAL: * Returns the alias descriptors hashtable. */ public Map getAliasDescriptors() { return project.getAliasDescriptors(); } /** * INTERNAL: * Allow the session to be used from a session broker. */ public AbstractSession getBroker() { return broker; } /** * INTERNAL: * The session that this query is executed against when not in transaction. * The session containing the shared identity map. *

* In most cases this is the root ServerSession or DatabaseSession. *

* In cases where objects are not to be cached in the global identity map * an alternate session may be returned: *

    *
  • A ClientSession if in transaction *
  • An isolated ClientSession or HistoricalSession *
  • A registered session of a root SessionBroker *
*/ public AbstractSession getRootSession(DatabaseQuery query) { return getParentIdentityMapSession(query, false, true); } /** * INTERNAL: * Gets the next link in the chain of sessions followed by a query's check * early return, the chain of sessions with identity maps all the way up to * the root session. */ public AbstractSession getParentIdentityMapSession(DatabaseQuery query) { return getParentIdentityMapSession(query, false, false); } /** * INTERNAL: * Gets the next link in the chain of sessions followed by a query's check * early return, the chain of sessions with identity maps all the way up to * the root session. *

* Used for session broker which delegates to registered sessions, or UnitOfWork * which checks parent identity map also. * @param canReturnSelf true when method calls itself. If the path * starting at this is acceptable. Sometimes true if want to * move to the first valid session, i.e. executing on ClientSession when really * should be on ServerSession. * @param terminalOnly return the session we will execute the call on, not * the next step towards it. * @return this if there is no next link in the chain */ public AbstractSession getParentIdentityMapSession(DatabaseQuery query, boolean canReturnSelf, boolean terminalOnly) { return this; } /** * INTERNAL: * Gets the session which this query will be executed on. * Generally will be called immediately before the call is translated, * which is immediately before session.executeCall. *

* Since the execution session also knows the correct datasource platform * to execute on, it is often used in the mappings where the platform is * needed for type conversion, or where calls are translated. *

* Is also the session with the accessor. Will return a ClientSession if * it is in transaction and has a write connection. * @return a session with a live accessor * @param query may store session name or reference class for brokers case */ public AbstractSession getExecutionSession(DatabaseQuery query) { return this; } /** * INTERNAL: * The commit manager is used to resolve referncial integrity on commits of multiple objects. * All brokered sessions share the same commit manager. */ public CommitManager getCommitManager() { if (hasBroker()) { return getBroker().getCommitManager(); } // PERF: lazy init, not always required, not required for client sessions if (commitManager == null) { commitManager = new CommitManager(this); } return commitManager; } /** * INTERNAL: * Returns the set of read-only classes that gets assigned to each newly created UnitOfWork. * * @see oracle.toplink.essentials.sessions.Project#setDefaultReadOnlyClasses(Vector) */ public Vector getDefaultReadOnlyClasses() { //Bug#3911318 All brokered sessions share the same DefaultReadOnlyClasses. if (hasBroker()) { return getBroker().getDefaultReadOnlyClasses(); } return getProject().getDefaultReadOnlyClasses(); } /** * ADVANCED: * Return the descriptor specified for the class. * If the class does not have a descriptor but implements an interface that is also implemented * by one of the classes stored in the hashtable, that descriptor will be stored under the * new class. */ public ClassDescriptor getClassDescriptor(Class theClass) { ClassDescriptor desc = getDescriptor(theClass); if (desc instanceof ClassDescriptor) { return (ClassDescriptor)desc; } else { throw ValidationException.cannotCastToClass(desc, desc.getClass(), ClassDescriptor.class); } } /** * ADVANCED: * Return the descriptor specified for the object's class. */ public ClassDescriptor getClassDescriptor(Object domainObject) { ClassDescriptor desc = getDescriptor(domainObject); if (desc instanceof ClassDescriptor) { return (ClassDescriptor)desc; } else { throw ValidationException.cannotCastToClass(desc, desc.getClass(), ClassDescriptor.class); } } /** * PUBLIC: * Return the descriptor for the alias. * UnitOfWork delegates this to the parent */ public ClassDescriptor getClassDescriptorForAlias(String alias) { return project.getClassDescriptorForAlias(alias); } /** * ADVANCED: * Return the descriptor specified for the class. * If the class does not have a descriptor but implements an interface that is also implemented * by one of the classes stored in the hashtable, that descriptor will be stored under the * new class. */ public ClassDescriptor getDescriptor(Class theClass) { if (theClass == null) { return null; } // Optimize descriptor lookup through caching the last one accessed. ClassDescriptor lastDescriptor = this.lastDescriptorAccessed; if ((lastDescriptor != null) && (lastDescriptor.getJavaClass().equals(theClass))) { return lastDescriptor; } ClassDescriptor descriptor = (ClassDescriptor)getDescriptors().get(theClass); if ((descriptor == null) && hasBroker()) { // Also check the broker descriptor = getBroker().getDescriptor(theClass); } if (descriptor == null) { // Allow for an event listener to lazy register the descriptor for a class. getEventManager().missingDescriptor(theClass); descriptor = (ClassDescriptor)getDescriptors().get(theClass); } if (descriptor == null) { // This allows for the correct descriptor to be found if the class implements an interface, // or extends a class that a descriptor is register for. // This is used by EJB to find the descriptor for a stub and remote to unwrap it, // and by inheritance to allow for subclasses that have no additional state to not require a descriptor. if (!theClass.isInterface()) { Class[] interfaces = theClass.getInterfaces(); for (int index = 0; index < interfaces.length; ++index) { Class interfaceClass = (Class)interfaces[index]; descriptor = getDescriptor(interfaceClass); if (descriptor != null) { getDescriptors().put(interfaceClass, descriptor); break; } } if (descriptor == null) { descriptor = getDescriptor(theClass.getSuperclass()); } } } // Cache for optimization. this.lastDescriptorAccessed = descriptor; return descriptor; } /** * ADVANCED: * Return the descriptor specified for the object's class. */ public ClassDescriptor getDescriptor(Object domainObject) { return getDescriptor(domainObject.getClass()); } /** * PUBLIC: * Return the descriptor for the alias */ public ClassDescriptor getDescriptorForAlias(String alias) { return project.getDescriptorForAlias(alias); } /** * ADVANCED: * Return all registered descriptors. */ public Map getDescriptors() { return getProject().getDescriptors(); } /** * ADVANCED: * Return all pre-defined not yet parsed EJBQL queries. * @see #getAllQueries() */ public List getEjbqlPlaceHolderQueries() { // PERF: lazy init, not normally required. if (ejbqlPlaceHolderQueries == null) { ejbqlPlaceHolderQueries = new Vector(); } return ejbqlPlaceHolderQueries; } /** * PUBLIC: * Return the event manager. * The event manager can be used to register for various session events. */ public synchronized SessionEventManager getEventManager() { if (eventManager == null) { // PERF: lazy init. eventManager = new SessionEventManager(this); } return eventManager; } /** * INTERNAL: * Return a string which represents my ExceptionHandler's class * Added for F2104: Properties.xml * - gn */ public String getExceptionHandlerClass() { String className = null; try { className = getExceptionHandler().getClass().getName(); } catch (Exception exception) { return null; } return className; } /** * PUBLIC: * Return the ExceptionHandler.Exception handler can catch errors that occur on queries or during database access. */ public ExceptionHandler getExceptionHandler() { return exceptionHandler; } /** * PUBLIC: * Used for JTS integration. If your application requires to have JTS control transactions instead of TopLink an * external transaction controler must be specified. * TopLink provides JTS controlers for several JTS implementations including JTS 1.0, Weblogic 5.1 and WebSphere 3.0. * * @see oracle.toplink.essentials.transaction.JTATransactionController */ public ExternalTransactionController getExternalTransactionController() { return externalTransactionController; } /** * PUBLIC: * The IdentityMapAccessor is the preferred way of accessing IdentityMap funcitons * This will return an object which implements an interface which exposes all public * IdentityMap functions. */ public oracle.toplink.essentials.sessions.IdentityMapAccessor getIdentityMapAccessor() { return identityMapAccessor; } /** * INTERNAL: * Return the internally available IdentityMapAccessor instance. */ public oracle.toplink.essentials.internal.sessions.IdentityMapAccessor getIdentityMapAccessorInstance() { return identityMapAccessor; } /** * PUBLIC: * Returns the integrityChecker.IntegrityChecker holds all the Descriptor Exceptions. */ public IntegrityChecker getIntegrityChecker() { // BUG# 2700595 - Lazily create an IntegrityChecker if one has not already been created. if (integrityChecker == null) { integrityChecker = new IntegrityChecker(); } return integrityChecker; } /** * PUBLIC: * Return the writer to which an accessor writes logged messages and SQL. * If not set, this reference defaults to a writer on System.out. * * @see #getSessionLog() */ public Writer getLog() { return getSessionLog().getWriter(); } /** * INTERNAL: * Return the name of the session: class name + system hashcode. *

* This should be the implementation of toString(), and also the * value should be calculated in the constructor for it is used all the * time. However everything is lazily initialized now and the value is * transient for the system hashcode could vary? */ public String getLogSessionString() { if (logSessionString == null) { StringWriter writer = new StringWriter(); writer.write(getSessionTypeString()); writer.write("("); writer.write(String.valueOf(System.identityHashCode(this))); writer.write(")"); logSessionString = writer.toString(); } return logSessionString; } /** * INTERNAL: * Returns the type of session, its class. *

* Override to hide from the user when they are using an internal subclass * of a known class. *

* A user does not need to know that their UnitOfWork is a * non-deferred UnitOfWork, or that their ClientSession is an * IsolatedClientSession. */ public String getSessionTypeString() { return Helper.getShortClassName(getClass()); } /** * INTERNAL: * Return the login, the login holds any database connection information given. * This has been replaced by getDatasourceLogin to make use of the Login interface * to support non-relational datasources, * if DatabaseLogin API is required it will need to be cast. */ public DatabaseLogin getLogin() { try { return (DatabaseLogin)getDatasourceLogin(); } catch (ClassCastException wrongType) { throw ValidationException.notSupportedForDatasource(); } } /** * PUBLIC: * Return the login, the login holds any database connection information given. * This return the Login interface and may need to be cast to the datasource specific implementation. */ public Login getDatasourceLogin() { return getProject().getDatasourceLogin(); } /** * PUBLIC: * Return the name of the session. * This is used with the session broker, or to give the session a more meaningful name. */ public String getName() { return name; } /** * ADVANCED: * Return the sequnce number from the database */ public Number getNextSequenceNumberValue(Class domainClass) { return (Number)getSequencing().getNextValue(domainClass); } /** * INTERNAL: * Return the number of units of work connected. */ public int getNumberOfActiveUnitsOfWork() { return numberOfActiveUnitsOfWork; } /** * PUBLIC: * Return the database platform currently connected to. * The platform is used for database specific behavoir. * NOTE: this must only be used for relational specific usage, * it will fail for non-relational datasources. */ public DatabasePlatform getPlatform() { return getDatasourceLogin().getPlatform(); } /** * PUBLIC: * Return the database platform currently connected to. * The platform is used for database specific behavoir. */ public Platform getDatasourcePlatform() { // PERF: Cache the platform. if (platform == null) { platform = getDatasourceLogin().getDatasourcePlatform(); } return platform; } /** * INTERNAL: * Marked internal as this is not customer API but helper methods for * accessing the server platform from within TopLink's other sessions types * (ie not DatabaseSession) */ public ServerPlatform getServerPlatform(){ return null; } /** * INTERNAL: * Return the database platform currently connected to * for specified class. * The platform is used for database specific behavoir. */ public Platform getPlatform(Class domainClass) { // PERF: Cache the platform. if (platform == null) { platform = getDatasourcePlatform(); } return platform; } /** * PUBLIC: * Return the profiler. * The profiler is a tool that can be used to determine performance bottlenecks. * The profiler can be queries to print summaries and configure for logging purposes. */ public SessionProfiler getProfiler() { return profiler; } /** * PUBLIC: * Return the project, the project holds configuartion information including the descriptors. */ public oracle.toplink.essentials.sessions.Project getProject() { return project; } /** * ADVANCED: * Allow for user defined properties. */ public Map getProperties() { if (properties == null) { properties = new HashMap(5); } return properties; } /** * INTERNAL: * Allow to check for user defined properties. */ public boolean hasProperties() { return ((properties != null) && !properties.isEmpty()); } /** * ADVANCED: * Returns the user defined property. */ public Object getProperty(String name) { return getProperties().get(name); } /** * ADVANCED: * Return all pre-defined queries. * @see #getAllQueries() */ public Map getQueries() { // PERF: lazy init, not normally required. if (queries == null) { queries = new HashMap(5); } return queries; } /** * PUBLIC: * Return the pre-defined queries in this session. * A single vector containing all the queries is returned. * * @see #getQueries() */ public Vector getAllQueries() { Vector allQueries = new Vector(); for (Iterator vectors = getQueries().values().iterator(); vectors.hasNext();) { allQueries.addAll((Vector)vectors.next()); } return allQueries; } /** * PUBLIC: * Return the query from the session pre-defined queries with the given name. * This allows for common queries to be pre-defined, reused and executed by name. */ public DatabaseQuery getQuery(String name) { return getQuery(name, null); } /** * PUBLIC: * Return the query from the session pre-defined queries with the given name and argument types. * This allows for common queries to be pre-defined, reused and executed by name. * This method should be used if the Session has multiple queries with the same name but * different arguments. * * @see #getQuery(String) */ public DatabaseQuery getQuery(String name, Vector arguments) { Vector queries = (Vector)getQueries().get(name); if ((queries == null) || queries.isEmpty()) { return null; } // Short circuit the simple, most common case of only one query. if (queries.size() == 1) { return (DatabaseQuery)queries.firstElement(); } // CR#3754; Predrag; mar 19/2002; // We allow multiple named queries with the same name but // different argument set; we can have only one query with // no arguments; Vector queries is not sorted; // When asked for the query with no parameters the // old version did return the first query - wrong: // return (DatabaseQuery) queries.firstElement(); int argumentTypesSize = 0; if (arguments != null) { argumentTypesSize = arguments.size(); } Vector argumentTypes = new Vector(argumentTypesSize); for (int i = 0; i < argumentTypesSize; i++) { argumentTypes.addElement(arguments.elementAt(i).getClass()); } for (Enumeration queriesEnum = queries.elements(); queriesEnum.hasMoreElements();) { DatabaseQuery query = (DatabaseQuery)queriesEnum.nextElement(); if (Helper.areTypesAssignable(argumentTypes, query.getArgumentTypes())) { return query; } } return null; } /** * INTERNAL: * Return the Sequencing object used by the session. */ public Sequencing getSequencing() { return null; } /** * INTERNAL: * Return the session to be used for the class. * Used for compatibility with the session broker. */ public AbstractSession getSessionForClass(Class domainClass) { if (hasBroker()) { return getBroker().getSessionForClass(domainClass); } return this; } /** * PUBLIC: * Return the session log to which an accessor logs messages and SQL. * If not set, this will default to a session log on a writer on System.out. */ public SessionLog getSessionLog() { if (sessionLog == null) { setSessionLog(new DefaultSessionLog()); } return sessionLog; } /** * INTERNAL: * The transaction mutex ensure mutual exclusion on transaction across multiple threads. */ public synchronized ConcurrencyManager getTransactionMutex() { // PERF: not always required, defer. if (transactionMutex == null) { transactionMutex = new ConcurrencyManager(); } return transactionMutex; } /** * PUBLIC: * Allow any WARNING level exceptions that occur within TopLink to be logged and handled by the exception handler. */ public Object handleException(RuntimeException exception) throws RuntimeException { if ((exception instanceof TopLinkException)) { TopLinkException topLinkException = (TopLinkException)exception; if (topLinkException.getSession() == null) { topLinkException.setSession(this); } //Bug#3559280 Avoid logging an exception twice if (!topLinkException.hasBeenLogged()) { logThrowable(SessionLog.WARNING, null, exception); topLinkException.setHasBeenLogged(true); } } else { logThrowable(SessionLog.WARNING, null, exception); } if (hasExceptionHandler()) { return getExceptionHandler().handleException(exception); } else { throw exception; } } /** * INTERNAL: * Allow the session to be used from a session broker. */ public boolean hasBroker() { return broker != null; } /** * ADVANCED: * Return true if a descriptor exists for the given class. */ public boolean hasDescriptor(Class theClass) { if (theClass == null) { return false; } return getDescriptors().get(theClass) != null; } /** * PUBLIC: * Return if an exception handler is present. */ public boolean hasExceptionHandler() { if (exceptionHandler == null) { return false; } return true; } /** * PUBLIC: * Used for JTA integration. If your application requires to have JTA control transactions instead of TopLink an * external transaction controler must be specified. TopLink provides JTA controlers for JTA 1.0 and application * servers. * @see oracle.toplink.essentials.transaction.JTATransactionController */ public boolean hasExternalTransactionController() { return externalTransactionController != null; } /** * INTERNAL: * Set up the IdentityMapManager. This method allows subclasses of Session to override * the default IdentityMapManager functionality. */ public void initializeIdentityMapAccessor() { this.identityMapAccessor = new oracle.toplink.essentials.internal.sessions.IdentityMapAccessor(this, new IdentityMapManager(this)); } /** * PUBLIC: * Insert the object and all of its privately owned parts into the database. * Insert should only be used if the application knows that the object is new, * otherwise writeObject should be used. * The insert operation can be customized through using an insert query. * * @exception DatabaseException if an error occurs on the database, * these include constraint violations, security violations and general database erros. * * @see InsertObjectQuery * @see #writeObject(Object) */ public Object insertObject(Object domainObject) throws DatabaseException { InsertObjectQuery query = new InsertObjectQuery(); query.setObject(domainObject); return executeQuery(query); } /** * INTERNAL: * Return the results from exeucting the database query. * The arguments should be a database row with raw data values. * This method is provided to allow subclasses to change the default querying behavoir. * All querying goes through this method. */ public Object internalExecuteQuery(DatabaseQuery query, AbstractRecord databaseRow) throws DatabaseException { return query.execute(this, databaseRow); } /** * INTERNAL: * Returns true if the session is a session Broker. */ public boolean isBroker() { return false; } /** * INTERNAL: * Returns true if the session is in a session Broker. */ public boolean isInBroker() { return false; } /** * PUBLIC: * Return if the class is defined as read-only. */ public boolean isClassReadOnly(Class theClass) { ClassDescriptor descriptor = getDescriptor(theClass); return isClassReadOnly(theClass, descriptor); } /** * INTERNAL: * Return if the class is defined as read-only. * PERF: Pass descriptor to avoid re-lookup. */ public boolean isClassReadOnly(Class theClass, ClassDescriptor descriptor) { if ((descriptor != null) && descriptor.shouldBeReadOnly()) { return true; } if (theClass != null) { return getDefaultReadOnlyClasses().contains(theClass); } return false; } /** * PUBLIC: * Return if this session is a client session. */ public boolean isClientSession() { return false; } /** * PUBLIC: * Return if this session is connected to the database. */ public boolean isConnected() { if (getAccessor() == null) { return false; } return getAccessor().isConnected(); } /** * PUBLIC: * Return if this session is a database session. */ public boolean isDatabaseSession() { return false; } /** * PUBLIC: * Return if this session is a distributed session. */ public boolean isDistributedSession() { return false; } /** * PUBLIC: * Return if a profiler is being used. */ public boolean isInProfile() { return isInProfile; } /** * PUBLIC: * Allow for user deactive a profiler */ public void setIsInProfile(boolean inProfile) { this.isInProfile = inProfile; } /** * PUBLIC: * Return if the session is currently in the progress of a database transaction. * Because nested transactions are allowed check if the transaction mutex has been aquired. */ public boolean isInTransaction() { return getTransactionMutex().isAcquired(); } /** * PUBLIC: * Return if this session is remote. */ public boolean isRemoteSession() { return false; } /** * PUBLIC: * Return if this session is a unit of work. */ public boolean isRemoteUnitOfWork() { return false; } /** * PUBLIC: * Return if this session is a server session. */ public boolean isServerSession() { return false; } /** * PUBLIC: * Return if this session is a session broker. */ public boolean isSessionBroker() { return false; } /** * PUBLIC: * Return if this session is a unit of work. */ public boolean isUnitOfWork() { return false; } /** * ADVANCED: * Extract and return the primary key from the object. */ public Vector keyFromObject(Object domainObject) throws ValidationException { ClassDescriptor descriptor = getDescriptor(domainObject); return keyFromObject(domainObject, descriptor); } /** * ADVANCED: * Extract and return the primary key from the object. */ public Vector keyFromObject(Object domainObject, ClassDescriptor descriptor) throws ValidationException { if (descriptor == null) { throw ValidationException.missingDescriptor(domainObject.getClass().getName()); } Object implemention = descriptor.getObjectBuilder().unwrapObject(domainObject, this); if (implemention == null) { return null; } return descriptor.getObjectBuilder().extractPrimaryKeyFromObject(implemention, this); } /** * PUBLIC: * Log the log entry. */ public void log(SessionLogEntry entry) { if (shouldLog(entry.getLevel(), entry.getNameSpace())) { if (entry.getSession() == null) {// Used for proxy session. entry.setSession(this); } getSessionLog().log(entry); } } /** * Log a untranslated message to the TopLink log at FINER level. */ public void logMessage(String message) { log(SessionLog.FINER, message, (Object[])null, null, false); } /** * INTERNAL: * A call back to do session specific preparation of a query. *

* The call back occurs soon before we clone the query for execution, * meaning that if this method needs to clone the query then the caller will * determine that it doesn't need to clone the query itself. */ public DatabaseQuery prepareDatabaseQuery(DatabaseQuery query) { if (!isUnitOfWork() && query.isObjectLevelReadQuery()) { return ((ObjectLevelReadQuery)query).prepareOutsideUnitOfWork(this); } else { return query; } } /** * INTERNAL: * Allows for EJBQL strings to be parsed and added as named queries. Should * be called after descriptors have been initialized to ensure all mappings * exist. */ public void processEJBQLQueries() { List queries = getEjbqlPlaceHolderQueries(); processEJBQLQueries(queries); queries.clear(); } /** * INTERNAL: * Allows for EJBQL strings to be parsed and added as named queries. Should * be called after descriptors have been initialized to ensure all mappings * exist. */ public void processEJBQLQueries(List queries) { for (Iterator iterator = queries.iterator(); iterator.hasNext();) { EJBQLPlaceHolderQuery existingQuery = (EJBQLPlaceHolderQuery)iterator.next(); this.addQuery(existingQuery.processEjbQLQuery(this)); } } /** * PUBLIC: * Read all of the instances of the class from the database. * This operation can be customized through using a ReadAllQuery, * or through also passing in a selection criteria. * * @see ReadAllQuery * @see #readAllObjects(Class, Expression) */ public Vector readAllObjects(Class domainClass) throws DatabaseException { ReadAllQuery query = new ReadAllQuery(); query.setReferenceClass(domainClass); return (Vector)executeQuery(query); } /** * PUBLIC: * Read all of the instances of the class from the database return through execution the SQL string. * The SQL string must be a valid SQL select statement or selecting stored procedure call. * This operation can be customized through using a ReadAllQuery. * * @see ReadAllQuery */ public Vector readAllObjects(Class domainClass, String sqlString) throws DatabaseException { ReadAllQuery query = new ReadAllQuery(); query.setReferenceClass(domainClass); query.setSQLString(sqlString); return (Vector)executeQuery(query); } /** * PUBLIC: * Read all the instances of the class from the database returned through execution the Call string. * The Call can be an SQLCall or EJBQLCall. * * example: session.readAllObjects(Employee.class, new SQLCall("SELECT * FROM EMPLOYEE")); * @see Call */ public Vector readAllObjects(Class referenceClass, Call aCall) throws DatabaseException { ReadAllQuery raq = new ReadAllQuery(); raq.setReferenceClass(referenceClass); raq.setCall(aCall); return (Vector)executeQuery(raq); } /** * PUBLIC: * Read all of the instances of the class from the database matching the given expression. * This operation can be customized through using a ReadAllQuery. * * @see ReadAllQuery */ public Vector readAllObjects(Class domainClass, Expression expression) throws DatabaseException { ReadAllQuery query = new ReadAllQuery(); query.setReferenceClass(domainClass); query.setSelectionCriteria(expression); return (Vector)executeQuery(query); } /** * PUBLIC: * Read the first instance of the class from the database. * This operation can be customized through using a ReadObjectQuery, * or through also passing in a selection criteria. * * @see ReadObjectQuery * @see #readAllObjects(Class, Expression) */ public Object readObject(Class domainClass) throws DatabaseException { ReadObjectQuery query = new ReadObjectQuery(); query.setReferenceClass(domainClass); return executeQuery(query); } /** * PUBLIC: * Read the first instance of the class from the database return through execution the SQL string. * The SQL string must be a valid SQL select statement or selecting stored procedure call. * This operation can be customized through using a ReadObjectQuery. * * @see ReadObjectQuery */ public Object readObject(Class domainClass, String sqlString) throws DatabaseException { ReadObjectQuery query = new ReadObjectQuery(); query.setReferenceClass(domainClass); query.setSQLString(sqlString); return executeQuery(query); } /** * PUBLIC: * Read the first instance of the class from the database returned through execution the Call string. * The Call can be an SQLCall or EJBQLCall. * * example: session.readObject(Employee.class, new SQLCall("SELECT * FROM EMPLOYEE")); * @see SQLCall * @see EJBQLCall */ public Object readObject(Class domainClass, Call aCall) throws DatabaseException { ReadObjectQuery query = new ReadObjectQuery(); query.setReferenceClass(domainClass); query.setCall(aCall); return executeQuery(query); } /** * PUBLIC: * Read the first instance of the class from the database matching the given expression. * This operation can be customized through using a ReadObjectQuery. * * @see ReadObjectQuery */ public Object readObject(Class domainClass, Expression expression) throws DatabaseException { ReadObjectQuery query = new ReadObjectQuery(); query.setReferenceClass(domainClass); query.setSelectionCriteria(expression); return executeQuery(query); } /** * PUBLIC: * Use the example object to consruct a read object query by the objects primary key. * This will read the object from the database with the same primary key as the object * or null if no object is found. */ public Object readObject(Object object) throws DatabaseException { ReadObjectQuery query = new ReadObjectQuery(); query.setSelectionObject(object); return executeQuery(query); } /** * PUBLIC: * Refresh the attributes of the object and of all of its private parts from the database. * The object will be pessimisticly locked on the database for the duration of the transaction. * If the object is already locked this method will wait until the lock is released. * A no wait option is available through setting the lock mode. * @see #refreshAndLockObject(Object, lockMode) */ public Object refreshAndLockObject(Object object) throws DatabaseException { ReadObjectQuery query = new ReadObjectQuery(); query.setSelectionObject(object); query.refreshIdentityMapResult(); query.cascadePrivateParts(); query.setLockMode(ObjectBuildingQuery.LOCK); return executeQuery(query); } /** * PUBLIC: * Refresh the attributes of the object and of all of its private parts from the database. * The object will be pessimisticly locked on the database for the duration of the transaction. *

Lock Modes: ObjectBuildingQuery.NO_LOCK, LOCK, LOCK_NOWAIT */ public Object refreshAndLockObject(Object object, short lockMode) throws DatabaseException { ReadObjectQuery query = new ReadObjectQuery(); query.setSelectionObject(object); query.refreshIdentityMapResult(); query.cascadePrivateParts(); query.setLockMode(lockMode); return executeQuery(query); } /** * PUBLIC: * Refresh the attributes of the object and of all of its private parts from the database. * This can be used to ensure the object is up to date with the database. * Caution should be used when using this to make sure the application has no un commited * changes to the object. */ public Object refreshObject(Object object) throws DatabaseException { return refreshAndLockObject(object, ObjectBuildingQuery.NO_LOCK); } /** * PUBLIC: * Release the session. * This does nothing by default, but allows for other sessions such as the ClientSession to do something. */ public void release() { } /** * INTERNAL: * Release the unit of work, if lazy release the connection. */ public void releaseUnitOfWork(UnitOfWorkImpl unitOfWork) { // Nothing is required by default, allow subclasses to do cleanup. setNumberOfActiveUnitsOfWork(getNumberOfActiveUnitsOfWork() - 1); } /** * PUBLIC: * Remove the user defined property. */ public void removeProperty(String property) { getProperties().remove(property); } /** * PUBLIC: * Remove all queries with the given queryName regardless of the argument types. * * @see #removeQuery(String, Vector) */ public void removeQuery(String queryName) { getQueries().remove(queryName); } /** * PUBLIC: * Remove the specific query with the given queryName and argumentTypes. */ public void removeQuery(String queryName, Vector argumentTypes) { Vector queries = (Vector)getQueries().get(queryName); if (queries == null) { return; } else { DatabaseQuery query = null; for (Enumeration enumtr = queries.elements(); enumtr.hasMoreElements();) { query = (DatabaseQuery)enumtr.nextElement(); if (Helper.areTypesAssignable(argumentTypes, query.getArgumentTypes())) { break; } } if (query != null) { queries.remove(query); } } } /** * PROTECTED: * Attempts to rollback the running internally started external transaction. * Returns true only in one case - * extenal transaction has been internally rolled back during this method call: * wasJTSTransactionInternallyStarted()==true in the beginning of this method and * wasJTSTransactionInternallyStarted()==false in the end of this method. */ protected boolean rollbackExternalTransaction() { boolean externalTransactionHasRolledBack = false; if (hasExternalTransactionController() && wasJTSTransactionInternallyStarted()) { try { getExternalTransactionController().rollbackTransaction(this); } catch (RuntimeException exception) { handleException(exception); } if (!wasJTSTransactionInternallyStarted()) { externalTransactionHasRolledBack = true; log(SessionLog.FINER, SessionLog.TRANSACTION, "external_transaction_has_rolled_back_internally"); } } return externalTransactionHasRolledBack; } /** * PUBLIC: * Rollback the active database transaction. * This allows a group of database modification to be commited or rolledback as a unit. * All writes/deletes will be sent to the database be will not be visible to other users until commit. * Although databases do not allow nested transaction, * TopLink supports nesting through only committing to the database on the outer commit. * * @exception DatabaseException if the database connection is lost or the rollback fails. * @exception ConcurrencyException if this session is not within a transaction. */ public void rollbackTransaction() throws DatabaseException, ConcurrencyException { // Ensure release of mutex and call subclass specific release. try { if (!getTransactionMutex().isNested()) { getEventManager().preRollbackTransaction(); basicRollbackTransaction(); getEventManager().postRollbackTransaction(); } } finally { getTransactionMutex().release(); // If there is no db transaction in progress // if there is an active external transaction // which was started internally - it should be rolled back internally, too. if (!isInTransaction()) { rollbackExternalTransaction(); } } } /** * INTERNAL: * Set the accessor. */ public void setAccessor(Accessor accessor) { this.accessor = accessor; } /** * INTERNAL: * Allow the session to be used from a session broker. */ public void setBroker(AbstractSession broker) { this.broker = broker; } /** * INTERNAL: * The commit manager is used to resolve referncial integrity on commits of multiple objects. */ public void setCommitManager(CommitManager commitManager) { this.commitManager = commitManager; } /** * INTERNAL: * Set the event manager. * The event manager can be used to register for various session events. */ public void setEventManager(SessionEventManager eventManager) { if (eventManager != null) { this.eventManager = eventManager; } else { this.eventManager = new SessionEventManager(); } this.eventManager.setSession(this); } /** * PUBLIC: * Set the exceptionHandler. * Exception handler can catch errors that occur on queries or during database access. */ public void setExceptionHandler(ExceptionHandler exceptionHandler) { this.exceptionHandler = exceptionHandler; } /** * Used for JTS integration internally by ServerPlatform. */ public void setExternalTransactionController(ExternalTransactionController externalTransactionController) { this.externalTransactionController = externalTransactionController; if (externalTransactionController == null) { return; } externalTransactionController.setSession(this); } /** * PUBLIC: * set the integrityChecker. IntegrityChecker holds all the Descriptor Exceptions. */ public void setIntegrityChecker(IntegrityChecker integrityChecker) { this.integrityChecker = integrityChecker; } /** * PUBLIC: * Set the writer to which an accessor writes logged messages and SQL. * If not set, this reference defaults to a writer on System.out. * * @see #setSessionLog(SessionLog) */ public void setLog(Writer log) { getSessionLog().setWriter(log); } /** * PUBLIC: * Set the login. */ public void setLogin(DatabaseLogin login) { setDatasourceLogin(login); } /** * PUBLIC: * Set the login. */ public void setLogin(Login login) { setDatasourceLogin(login); } /** * PUBLIC: * Set the login. */ public void setDatasourceLogin(Login login) { getProject().setDatasourceLogin(login); } /** * PUBLIC: * Set the name of the session. * This is used with the session broker. */ public void setName(String name) { this.name = name; } protected void setNumberOfActiveUnitsOfWork(int numberOfActiveUnitsOfWork) { this.numberOfActiveUnitsOfWork = numberOfActiveUnitsOfWork; } /** * PUBLIC: * Set the profiler for the session. * This allows for performance operations to be profiled. */ public void setProfiler(SessionProfiler profiler) { this.profiler = profiler; if (profiler != null) { profiler.setSession(this); setIsInProfile(getProfiler().getProfileWeight() != SessionProfiler.NONE); // Clear cached flag that bybasses the profiler check. getIdentityMapAccessorInstance().getIdentityMapManager().clearCacheAccessPreCheck(); } else { setIsInProfile(false); } } /** * INTERNAL: * Set the project, the project holds configuartion information including the descriptors. */ public void setProject(oracle.toplink.essentials.sessions.Project project) { this.project = project; } /** * INTERNAL: * Set the user defined properties. */ public void setProperties(Hashtable properties) { this.properties = properties; } /** * PUBLIC: * Allow for user defined properties. */ public void setProperty(String propertyName, Object propertyValue) { getProperties().put(propertyName, propertyValue); } protected void setQueries(Hashtable queries) { this.queries = queries; } /** * PUBLIC: * Set the session log to which an accessor logs messages and SQL. * If not set, this will default to a session log on a writer on System.out. * To enable logging, log level can not be OFF. * Also set a backpointer to this session in SessionLog. To avoid a sessionLog * being shared by more than one session, it needs to be cloned. * * @see #logMessage(String) */ public void setSessionLog(SessionLog sessionLog) { this.sessionLog = (SessionLog)((AbstractSessionLog)sessionLog).clone(); if (this.sessionLog != null) { this.sessionLog.setSession(this); } } protected void setTransactionMutex(ConcurrencyManager transactionMutex) { this.transactionMutex = transactionMutex; } /** * INTERNAL: * Return if a JTS transaction was started by the session. * The session will start a JTS transaction if a unit of work or transaction is begun without a JTS transaction present. */ public void setWasJTSTransactionInternallyStarted(boolean wasJTSTransactionInternallyStarted) { this.wasJTSTransactionInternallyStarted = wasJTSTransactionInternallyStarted; } /** * PUBLIC: * Return if logging is enabled (false if log level is OFF) */ public boolean shouldLogMessages() { if (getLogLevel(null) == SessionLog.OFF) { return false; } else { return true; } } /** * INTERNAL: * Start the operation timing. */ public void startOperationProfile(String operationName) { if (isInProfile()) { getProfiler().startOperationProfile(operationName); } } /** * Print the connection status with the session. */ public String toString() { StringWriter writer = new StringWriter(); writer.write(getSessionTypeString() + "(" + Helper.cr() + "\t" + getAccessor() + Helper.cr() + "\t" + getDatasourcePlatform() + ")"); return writer.toString(); } /** * INTERNAL: * Unwrap the object if required. * This is used for the wrapper policy support and EJB. */ public Object unwrapObject(Object proxy) { return getDescriptor(proxy).getObjectBuilder().unwrapObject(proxy, this); } /** * PUBLIC: * Update the object and all of its privately owned parts in the database. * Update should only be used if the application knows that the object is new, * otherwise writeObject should be used. * The update operation can be customized through using an update query. * * @exception DatabaseException if an error occurs on the database, * these include constraint violations, security violations and general database erros. * @exception OptimisticLockException if the object's descriptor is using optimistic locking and * the object has been updated or deleted by another user since it was last read. * * @see UpdateObjectQuery * @see #writeObject(Object) */ public Object updateObject(Object domainObject) throws DatabaseException, OptimisticLockException { UpdateObjectQuery query = new UpdateObjectQuery(); query.setObject(domainObject); return executeQuery(query); } /** * INTERNAL: * This method will be used to update the query with any settings required * For this session. It can also be used to validate execution. */ public void validateQuery(DatabaseQuery query) { // a no-op for this class } /** * TESTING: * This is used by testing code to ensure that a deletion was successful. */ public boolean verifyDelete(Object domainObject) { ObjectBuilder builder = getDescriptor(domainObject).getObjectBuilder(); Object implementation = builder.unwrapObject(domainObject, this); return builder.verifyDelete(implementation, this); } /** * INTERNAL: * Return if a JTS transaction was started by the session. * The session will start a JTS transaction if a unit of work or transaction is begun without a JTS transaction present. */ public boolean wasJTSTransactionInternallyStarted() { return wasJTSTransactionInternallyStarted; } /** * INTERNAL: * Wrap the object if required. * This is used for the wrapper policy support and EJB. */ public Object wrapObject(Object implementation) { return getDescriptor(implementation).getObjectBuilder().wrapObject(implementation, this); } /** * INTERNAL: * Write all of the objects and all of their privately owned parts in the database. * The allows for a group of new objects to be commited as a unit. * The objects will be commited through a single transactions and any * foreign keys/circular references between the objects will be resolved. */ protected void writeAllObjects(IdentityHashtable domainObjects) throws DatabaseException, OptimisticLockException { getCommitManager().commitAllObjects(domainObjects); } /** * INTERNAL: * Write all of the objects and all of their privately owned parts in the database. * The allows for a group of new objects to be commited as a unit. * The objects will be commited through a single transactions and any * foreign keys/circular references between the objects will be resolved. */ protected void writeAllObjectsWithChangeSet(UnitOfWorkChangeSet uowChangeSet) throws DatabaseException, OptimisticLockException { getCommitManager().commitAllObjectsWithChangeSet(uowChangeSet); } /** * PUBLIC: * Write the object and all of its privately owned parts in the database. * Write will determine if an insert or an update should be done, * it may go to the database to determine this (by default will check the identity map). * The write operation can be customized through using an write query. * * @exception DatabaseException if an error occurs on the database, * these include constraint violations, security violations and general database erros. * @exception OptimisticLockException if the object's descriptor is using optimistic locking and * the object has been updated or deleted by another user since it was last read. * * @see WriteObjectQuery * @see #insertObject(Object) * @see #updateObject(Object) */ public Object writeObject(Object domainObject) throws DatabaseException, OptimisticLockException { WriteObjectQuery query = new WriteObjectQuery(); query.setObject(domainObject); return executeQuery(query); } /** * INTERNAL: * This method notifies the accessor that a particular sets of writes has * completed. This notification can be used for such thing as flushing the * batch mechanism */ public void writesCompleted() { getAccessor().writesCompleted(this); } /** * PUBLIC: *

* Return the log level *

* * @return the log level *

* @param category the string representation of a TopLink category, e.g. "sql", "transaction" ... *

*/ public int getLogLevel(String category) { return getSessionLog().getLevel(category); } /** * PUBLIC: *

* Return the log level *

* @return the log level *

*/ public int getLogLevel() { return getSessionLog().getLevel(); } /** * PUBLIC: *

* Set the log level *

* * @param level the new log level *

*/ public void setLogLevel(int level) { getSessionLog().setLevel(level); } /** * PUBLIC: *

* Check if a message of the given level would actually be logged. *

* * @return true if the given message level will be logged *

* @param level the log request level * @param category the string representation of a TopLink category *

*/ public boolean shouldLog(int Level, String category) { return getSessionLog().shouldLog(Level, category); } /** * PUBLIC: *

* Log a message with level and category that needs to be translated. *

* * @param level the log request level value *

* @param message the string message *

* @param category the string representation of a TopLink category. *

*/ public void log(int level, String category, String message) { if (!shouldLog(level, category)) { return; } log(level, category, message, (Object[])null); } /** * INTERNAL: *

* Log a message with level, category and a parameter that needs to be translated. *

* * @param level the log request level value *

* @param message the string message *

* @param category the string representation of a TopLink category. *

* @param param a parameter of the message *

*/ public void log(int level, String category, String message, Object param) { if (!shouldLog(level, category)) { return; } log(level, category, message, new Object[] { param }); } /** * INTERNAL: *

* Log a message with level, category and two parameters that needs to be translated. *

* * @param level the log request level value *

* @param message the string message *

* @param category the string representation of a TopLink category. *

* @param param1 a parameter of the message *

* @param param2 second parameter of the message *

*/ public void log(int level, String category, String message, Object param1, Object param2) { if (!shouldLog(level, category)) { return; } log(level, category, message, new Object[] { param1, param2 }); } /** * INTERNAL: *

* Log a message with level, category and three parameters that needs to be translated. *

* * @param level the log request level value *

* @param message the string message *

* @param category the string representation of a TopLink category. *

* @param param1 a parameter of the message *

* @param param2 second parameter of the message *

* @param param3 third parameter of the message *

*/ public void log(int level, String category, String message, Object param1, Object param2, Object param3) { if (!shouldLog(level, category)) { return; } log(level, category, message, new Object[] { param1, param2, param3 }); } /** * INTERNAL: *

* Log a message with level, category and an array of parameters that needs to be translated. *

* * @param level the log request level value *

* @param message the string message *

* @param category the string representation of a TopLink category. *

* @param params array of parameters to the message *

*/ public void log(int level, String category, String message, Object[] params) { log(level, category, message, params, null); } /** * INTERNAL: *

* Log a message with level, category, parameters and accessor that needs to be translated. *

* * @param level the log request level value *

* @param message the string message *

* @param params array of parameters to the message *

* @param accessor the connection that generated the log entry *

* @param category the string representation of a TopLink category. *

*/ public void log(int level, String category, String message, Object[] params, Accessor accessor) { log(level, category, message, params, accessor, true); } /** * INTERNAL: *

* Log a message with level, category, parameters and accessor. shouldTranslate determines if the message needs to be translated. *

* * @param level the log request level value *

* @param message the string message *

* @param params array of parameters to the message *

* @param accessor the connection that generated the log entry *

* @param category the string representation of a TopLink category. *

* @param shouldTranslate true if the message needs to be translated. *

*/ public void log(int level, String category, String message, Object[] params, Accessor accessor, boolean shouldTranslate) { if (shouldLog(level, category)) { startOperationProfile(SessionProfiler.Logging); log(new SessionLogEntry(level, category, this, message, params, accessor, shouldTranslate)); endOperationProfile(SessionProfiler.Logging); } } /** * INTERNAL: *

* Log a message with level, parameters and accessor that needs to be translated. *

* * @param level the log request level value *

* @param message the string message *

* @param params array of parameters to the message *

* @param accessor the connection that generated the log entry *

*/ public void log(int level, String message, Object[] params, Accessor accessor) { log(level, message, params, accessor, true); } /** * INTERNAL: *

* Log a message with level, parameters and accessor. shouldTranslate determines if the message needs to be translated. *

* * @param level the log request level value *

* @param message the string message *

* @param params array of parameters to the message *

* @param accessor the connection that generated the log entry *

* @param shouldTranslate true if the message needs to be translated. *

*/ public void log(int level, String message, Object[] params, Accessor accessor, boolean shouldTranslate) { if (shouldLog(level, null)) { startOperationProfile(SessionProfiler.Logging); log(new SessionLogEntry(level, this, message, params, accessor, shouldTranslate)); endOperationProfile(SessionProfiler.Logging); } } /** * PUBLIC: *

* Log a throwable with level and category. *

* * @param level the log request level value *

* @param category the string representation of a TopLink category. *

* @param throwable a Throwable *

*/ public void logThrowable(int level, String category, Throwable throwable) { // Must not create the log if not logging as is a performance issue. if (shouldLog(level, category)) { startOperationProfile(SessionProfiler.Logging); log(new SessionLogEntry(this, level, category, throwable)); endOperationProfile(SessionProfiler.Logging); } } /** * PUBLIC: *

* This method is called when a severe level message needs to be logged. * The message will be translated *

* * @param message the message key *

*/ public void severe(String message, String category) { log(SessionLog.SEVERE, category, message); } /** * PUBLIC: *

* This method is called when a warning level message needs to be logged. * The message will be translated *

* * @param message the message key *

*/ public void warning(String message, String category) { log(SessionLog.WARNING, category, message); } /** * PUBLIC: *

* This method is called when a info level message needs to be logged. * The message will be translated *

* * @param message the message key *

*/ public void info(String message, String category) { log(SessionLog.INFO, category, message); } /** * PUBLIC: *

* This method is called when a config level message needs to be logged. * The message will be translated *

* * @param message the message key *

*/ public void config(String message, String category) { log(SessionLog.CONFIG, category, message); } /** * PUBLIC: *

* This method is called when a fine level message needs to be logged. * The message will be translated *

* * @param message the message key *

*/ public void fine(String message, String category) { log(SessionLog.FINE, category, message); } /** * PUBLIC: *

* This method is called when a finer level message needs to be logged. * The message will be translated *

* * @param message the message key *

*/ public void finer(String message, String category) { log(SessionLog.FINER, category, message); } /** * PUBLIC: *

* This method is called when a finest level message needs to be logged. * The message will be translated *

* * @param message the message key *

*/ public void finest(String message, String category) { log(SessionLog.FINEST, category, message); } /** * PUBLIC: * Allow any SEVERE level exceptions that occur within TopLink to be logged and handled by the exception handler. */ public Object handleSevere(RuntimeException exception) throws RuntimeException { logThrowable(SessionLog.SEVERE, null, exception); if (hasExceptionHandler()) { return getExceptionHandler().handleException(exception); } else { throw exception; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy