# RemotePersistence.java

    /*
    ** Module   : RemotePersistence.java
    ** Abstract : Persistence subclass which delegates some services to a remote P2J server
    **
    ** Copyright (c) 2004-2024, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- --JPRM-- -----------------------------------Description-----------------------------------
    ** 001 ECF 20071018   @35556 Created initial version. Persistence subclass
    **                           which delegates some services to a remote
    **                           server.
    ** 002 ECF 20071115   @35912 Completed initial implementation. Obtain
    **                           network proxies for LockManagerMultiplexer
    **                           and DirtyReadMultiplexer to enable remote
    **                           lock management and dirty read management.
    ** 003 SVL 20080111   @36771 Unnecessary parameter 'database' removed from
    **                           createLockManager() and
    **                           createDirtyReadManager() functions.
    **                           createIdentityManager() function added.
    ** 004 ECF 20080611   @38707 Removed all references to DirtyReadManager
    **                           related classes. This hierarchy has been
    **                           obsoleted by the persist.dirty package.
    ** 005 ECF 20080806   @39308 Modified to conform to new IdentityManager API.
    ** 006 ECF 20131028          Import change.
    ** 007 ECF 20200906          New ORM implementation.
    ** 008 TJD 20240918          Defer tenant initialization for remote databases
    ** 009 OM  20241128          Multi-tenant runtime support: selected the proper persistence context, eventually
    **                           based on [sharedDb] parameter.
    */

    /*
    ** This program is free software: you can redistribute it and/or modify
    ** it under the terms of the GNU Affero General Public License as
    ** published by the Free Software Foundation, either version 3 of the
    ** License, or (at your option) any later version.
    **
    ** This program is distributed in the hope that it will be useful,
    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    ** GNU Affero General Public License for more details.
    **
    ** You may find a copy of the GNU Affero GPL version 3 at the following
    ** location: https://www.gnu.org/licenses/agpl-3.0.en.html
    **
    ** Additional terms under GNU Affero GPL version 3 section 7:
    **
    **   Under Section 7 of the GNU Affero GPL version 3, the following additional
    **   terms apply to the works covered under the License.  These additional terms
    **   are non-permissive additional terms allowed under Section 7 of the GNU
    **   Affero GPL version 3 and may not be removed by you.
    **
    **   0. Attribution Requirement.
    **
    **     You must preserve all legal notices or author attributions in the covered
    **     work or Appropriate Legal Notices displayed by works containing the covered
    **     work.  You may not remove from the covered work any author or developer
    **     credit already included within the covered work.
    **
    **   1. No License To Use Trademarks.
    **
    **     This license does not grant any license or rights to use the trademarks
    **     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
    **     of Golden Code Development Corporation. You are not authorized to use the
    **     name Golden Code, FWD, or the names of any author or contributor, for
    **     publicity purposes without written authorization.
    **
    **   2. No Misrepresentation of Affiliation.
    **
    **     You may not represent yourself as Golden Code Development Corporation or FWD.
    **
    **     You may not represent yourself for publicity purposes as associated with
    **     Golden Code Development Corporation, FWD, or any author or contributor to
    **     the covered work, without written authorization.
    **
    **   3. No Misrepresentation of Source or Origin.
    **
    **     You may not represent the covered work as solely your work.  All modified
    **     versions of the covered work must be marked in a reasonable way to make it
    **     clear that the modified work is not originating from Golden Code Development
    **     Corporation or FWD.  All modified versions must contain the notices of
    **     attribution required in this license.
    */

    package com.goldencode.p2j.persist.remote;

    import com.goldencode.p2j.net.*;
    import com.goldencode.p2j.persist.*;
    import com.goldencode.p2j.persist.dialect.*;
    import com.goldencode.p2j.persist.id.*;
    import com.goldencode.p2j.persist.lock.*;

    /**
     * A subclass of {@link Persistence} which is intended to be used with a
     * database instance managed by a remote P2J server.  Most work is executed
     * directly against the database via Hibernate;  however, certain services
     * must be serialized through the remote P2J server instance.  These include:
     * <ul>
     *   <li><b>Record lock management</b>.  Record locking must be serialized
     *       through the P2J server instance which is authoritative for the target
     *       database, to ensure that the lock manager implementation in use for a
     *       given database can properly manage concurrent locking requests.  This
     *       is accomplished by instantiating a specialized {@link
     *       com.goldencode.p2j.persist.lock.LockManager LockManager} implementation
     *       ({@link RemoteLockManager}, which delegates requests for locking
     *       services to the remote server.
     *   <li><b>Primary key generation</b>.  Likewise, the management of new
     *       primary keys must be delegated to the remote server which is
     *       authoritative for the target database.  This is accomplished by
     *       instantiating a specialized {@link
     *       com.goldencode.p2j.persist.id.IdentityManager IdentityManager}
     *       implementation ({@link RemoteIdentityManager}).
     * </ul>
     *
     * @author ECF
     */
    public final class RemotePersistence
    extends Persistence
    {
       /** Network session with remote server */
       private final Session session;

       /**
        * Construct an instance for a particular, physical database, storing the
        * dialect class which Hibernate uses to create a portability layer.
        *
        * @param   database
        *          Database with which this instance is permanently associated.
        * @param   dialect
        *          Portability object used by Hibernate to issue commands to the
        *          database.
        */
       public RemotePersistence(Database database, Dialect dialect)
       {
          super(database, dialect);
          session = ConnectionManager.getSession(database);
          initializeTenant(defaultTenant);
       }

       /**
        * Create and initialize the lock manager to be used with this instance of
        * persistence services.
        *
        * @return  Lock manager instance.
        */
       protected LockManager createLockManager(int tenantId)
       {
          // Get lock manager multiplexer proxy.
          LockManagerMultiplexer multiplexer = (LockManagerMultiplexer)
             RemoteObject.obtainNetworkInstance(LockManagerMultiplexer.class, session);
          LockManager mgr = new RemoteLockManager(multiplexer);
          mgr.setDatabase(getDatabase(Persistence.META_CTX));

          return mgr;
       }

       /**
        * Create and initialize the identity manager to be used with this instance
        * of persistence services.
        *
        * @return  Identity manager instance.
        */
       protected IdentityManager createIdentityManager(int tenantId)
       {
          // Get identity manager multiplexer proxy.
          IdentityManagerMultiplexer multiplexer = (IdentityManagerMultiplexer)
             RemoteObject.obtainNetworkInstance(IdentityManagerMultiplexer.class, session);

          IdentityManager mgr = new RemoteIdentityManager(multiplexer);
          mgr.setPersistence(this);

          return mgr;
       }
    }