ConnectionFactoryManagerPeerImpl.java 19.1 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.transaction.RollbackException
 *  javax.transaction.SystemException
 *  javax.transaction.Transaction
 *  javax.transaction.TransactionManager
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.service;

import com.adobe.CORBA.ServantBase;
import com.adobe.aemds.bedrock.internal.OSGiUtils;
import com.adobe.service.*;
import com.adobe.service.impl.Platform;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Object;
import org.omg.CORBA.portable.ObjectImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.*;

/*
 * This class specifies class file version 49.0 but uses Java 6 signatures.  Assumed Java 6.
 */
class ConnectionFactoryManagerPeerImpl
extends ConnectionFactoryManagerPeer
implements ConnectionFactory {
    public static final String GLOBAL_TIMEOUT_ATTRIBUTE = "globalTimeout";
    private static final Logger logger = LoggerFactory.getLogger(ConnectionFactoryManagerPeerImpl.class);
    private static Timer interruptTimer = new Timer(true);
    private Map interruptTaskMap = Collections.synchronizedMap(new WeakHashMap());
    private Map<Transaction, ConnectionResource> connectionResourceMap = Collections.synchronizedMap(new WeakHashMap());
    private Transactable trans;

    ConnectionFactoryManagerPeerImpl(ConnectionFactoryManager connectionFactoryManager) {
        super(connectionFactoryManager);
        this.setTransactable(new SyncTransactable());
    }

    @Override
    public void setImpersonationIdentities(Map<String, String> credentialMap) {
        this.checkInitialized();
        ImpersonatedConnectionManager.addCredentials(this.connectionFactoryManager.service, credentialMap);
    }

    @Override
    public void clearImpersonationIdentities() {
        this.checkInitialized();
        ImpersonatedConnectionManager.removeCredentials(this.connectionFactoryManager.service);
    }

    @Override
    public void resetProcesses() {
        try {
            Transaction transaction = this.getTransaction();
            if (transaction == null) {
                throw new IllegalStateException("No transaction");
            }
            int transactionStatus = transaction.getStatus();
            if (transactionStatus != 0) {
                throw new IllegalStateException("Bad transaction status: " + transactionStatus);
            }
            this.checkInitialized();
            this.pooler.resetResources();
        }
        catch (SystemException e) {
            throw new UndeclaredThrowableException((Throwable)e, "Bad transaction while resetting processes");
        }
    }

    @Override
    public java.lang.Object getConnection() {
        logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " entering getConnection()");
        try {
            Transaction transaction = this.getTransaction();
            if (transaction == null) {
                throw new IllegalStateException("No transaction");
            }
            int transactionStatus = transaction.getStatus();
            if (transactionStatus != 0) {
                throw new IllegalStateException("Bad transaction status " + transactionStatus);
            }
            this.checkInitialized();
            long queueWaitBegin = System.currentTimeMillis();
            ConnectionResource cr = this.connectionResourceMap.get((java.lang.Object)transaction);
            if (cr == null) {
                cr = this.getConnectionResourceFromPool();
                ResourcePeer resourcePeer = cr.peer;
                try {
                    this.trans.enlist(transaction, (ResourcePeerImpl)resourcePeer);
                    resourcePeer.setSavedTx(transaction);
                    this.connectionResourceMap.put(transaction, cr);
                }
                catch (RollbackException e) {
                    logger.warn("Exception while enlisting resource with transaction", (Throwable)e);
                    resourcePeer.invokeRollback();
                    throw new IllegalStateException("Transaction rollback-only " + (java.lang.Object)e);
                }
                resourcePeer.invokeJoin();
            }
            if (cr.peer.getSavedTx() != transaction) {
                throw new IllegalStateException("Bad transaction lookup " + transactionStatus);
            }
            try {
                long timeout = this.getServiceTimeout();
                if (timeout < 0) {
                    logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " does not have the " + "globalTimeout" + " MBean attribute. No further interrupt processing will take place.");
                } else if (this.interruptTaskMap.containsKey((java.lang.Object)transaction)) {
                    logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " resource: " + cr + " has already scheduled an interrupt for transaction: " + (java.lang.Object)transaction + "." + " To override, use setCurrentInstanceTimeout(). No further interrupt processing will take place in getConnection().");
                } else {
                    long adjustment = (System.currentTimeMillis() - queueWaitBegin) / 1000;
                    long effectiveTimeout = timeout - adjustment;
                    if (effectiveTimeout >= 0) {
                        logger.info("Service: " + this.connectionFactoryManager.service.getName() + " resource: " + cr + " applying queue wait adjustment of " + adjustment + "s to" + " timeout of transaction: " + (java.lang.Object)transaction + "." + " Supplied timeout: " + timeout + "s," + " Effective timeout: " + effectiveTimeout + "s.");
                        this.scheduleInterrupt(effectiveTimeout, transaction);
                    } else {
                        logger.warn("Service: " + this.connectionFactoryManager.service.getName() + " resource: " + cr + " could not schedule an interrupt for transaction: " + (java.lang.Object)transaction + " because excessive time was spent waiting in queue." + " Supplied timeout: " + timeout + "s," + " Wait adjustment: " + adjustment + "s," + " Effective timeout: " + effectiveTimeout + "s.");
                    }
                }
                logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " resource: " + cr + " trying to allocate connection.");
                java.lang.Object connection = cr.getConnection();
                logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " resource: " + cr + " successfully allocated connection: " + connection);
                if (connection instanceof ServantBase) {
                    connection = ((ServantBase)connection)._this();
                }
                if (connection instanceof ObjectImpl) {
                    ObjectImpl objectImpl = (ObjectImpl)connection;
                    ORB orb = Platform.UTIL.getOrb();
                    String ior = orb.object_to_string(objectImpl);
                    connection = orb.string_to_object(ior);
                }
                return connection;
            }
            catch (Throwable e) {
                logger.error("Unexpected exception while getting connection", e);
                this.killProcess(transaction, true);
                if (e instanceof RuntimeException) {
                    throw (RuntimeException)e;
                }
                throw new UndeclaredThrowableException(e, "Bad Connection");
            }
        }
        catch (SystemException e) {
            throw new UndeclaredThrowableException((Throwable)e, "Bad transaction");
        }
    }

    @Override
    public void setServiceTimeout(long seconds) {
        logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " entering setServiceTimeout()");
        this.checkInitialized();
        long timeout = this.getServiceTimeout();
        if (timeout < 0) {
            throw new IllegalStateException("Service: " + this.connectionFactoryManager.service.getName() + " does not have configurable attribute: " + "globalTimeout");
        }
        if (seconds >= 0 && seconds != timeout) {
            this.connectionFactoryManager.service.setAttribute("globalTimeout", String.valueOf(seconds));
            logger.info("Service: " + this.connectionFactoryManager.service.getName() + " set " + "globalTimeout" + "=" + seconds + "s");
        }
    }

    @Override
    public void setCurrentInstanceTimeout(long seconds) {
        logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " entering setCurrentInstanceTimeout()");
        ConnectionResource cr = null;
        Transaction transaction = null;
        try {
            transaction = this.getTransaction();
            if (transaction == null) {
                throw new IllegalStateException("No transaction");
            }
            int transactionStatus = transaction.getStatus();
            if (transactionStatus != 0) {
                throw new IllegalStateException("Bad transaction status " + transactionStatus);
            }
            this.checkInitialized();
            cr = this.connectionResourceMap.get((java.lang.Object)transaction);
            if (cr == null) {
                throw new IllegalStateException("No resource enlisted with current transaction");
            }
        }
        catch (SystemException e) {
            throw new UndeclaredThrowableException((Throwable)e, "Bad transaction");
        }
        logger.debug("A timeout of " + seconds + "s has been specified on service " + this.connectionFactoryManager.service.getName() + " instance managed by: " + cr + " enlisted in transaction: " + (java.lang.Object)transaction);
        long applicableTimeout = -1;
        if (seconds < 0) {
            logger.warn("Invalid timeout specified for service instance managed by: " + cr + ", ignoring. " + "Checking for " + "globalTimeout" + " on service: " + this.connectionFactoryManager.service.getName());
            String sTimeout = this.connectionFactoryManager.service.getAttribute("globalTimeout");
            if (sTimeout != null) {
                try {
                    applicableTimeout = Long.parseLong(sTimeout);
                }
                catch (NumberFormatException nfe) {}
            }
        } else {
            applicableTimeout = seconds;
        }
        if (applicableTimeout < 0) {
            logger.warn("No valid timeout value could be obtained for service: " + this.connectionFactoryManager.service.getName() + ". No attempt will be made to monitor or abort this transaction.");
            return;
        }
        logger.info("Setting timeout of " + applicableTimeout + "s on service " + this.connectionFactoryManager.service.getName() + " instance managed by: " + cr + " enlisted in transaction: " + (java.lang.Object)transaction);
        this.scheduleInterrupt(applicableTimeout, transaction);
    }

    private void checkInitialized() {
        if (this.connectionFactoryManager.service.lazyInitialization) {
            this.connectionFactoryManager.service.deferredInitialize();
        }
    }

    @Override
    public ConnectionFactory getConnectionFactory() {
        return this;
    }

    protected void setTransactable(Transactable tr) {
        this.trans = tr;
    }

    private Transaction getTransaction() {
        TransactionManager transactionManager = OSGiUtils.getTransactionManager();
        try {
            return transactionManager.getTransaction();
        }
        catch (SystemException e) {
            logger.warn("Error getting active transaction", (Throwable)e);
            throw new IllegalStateException("No transaction " + (java.lang.Object)e);
        }
    }

    private void killProcess(Transaction transaction) throws SystemException {
        this.killProcess(transaction, false);
    }

    private void killProcess(Transaction transaction, boolean unconditional) throws SystemException {
        if (transaction != null) {
            TimerTask task = (TimerTask)this.interruptTaskMap.remove((java.lang.Object)transaction);
            if (task != null) {
                logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " cancelling timer: " + task + " for transaction: " + (java.lang.Object)transaction);
                task.cancel();
            }
            ConnectionResource cr = this.connectionResourceMap.remove((java.lang.Object)transaction);
            Transaction savedTx = ((ResourcePeerImpl)cr.peer).getSavedTx();
            logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " resource: " + cr + " allocated: " + cr.peer.allocated + " savedTx: " + (java.lang.Object)savedTx + " initialTx: " + (java.lang.Object)transaction + " unconditional terminate: " + unconditional);
            if (cr.peer.allocated && savedTx == transaction || unconditional) {
                logger.info("Service: " + this.connectionFactoryManager.service.getName() + " shutting down resource: " + cr);
                cr.onShutdown();
                ImpersonatedConnectionManager.releaseCredential(this.connectionFactoryManager.service, cr);
                cr.setReusable(false);
                ResourcePooler.onDeallocate(cr);
                this.trans.delist(transaction, (ResourcePeerImpl)cr.peer);
            }
        }
    }

    private long getServiceTimeout() {
        ServiceAPI svc = this.connectionFactoryManager.service;
        long timeout = -1;
        try {
            String sTimeout = svc.getAttribute("globalTimeout");
            if (sTimeout != null) {
                try {
                    timeout = Long.parseLong(sTimeout);
                    logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " retrieved " + "globalTimeout" + "=" + timeout + "s");
                }
                catch (NumberFormatException nfe) {}
            }
        }
        catch (Exception e) {
            logger.debug(e.getMessage());
        }
        return timeout;
    }

    private void scheduleInterrupt(long seconds, final Transaction transaction) {
        logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " attempting to schedule interrupt after " + seconds + "s for transaction: " + (java.lang.Object)transaction);
        if (seconds <= 0) {
            if (seconds == 0) {
                if (this.interruptTaskMap.containsKey((java.lang.Object)transaction)) {
                    logger.info("Service: " + this.connectionFactoryManager.service.getName() + " attempting to remove scheduled interrupt for transaction: " + (java.lang.Object)transaction);
                    TimerTask task = (TimerTask)this.interruptTaskMap.remove((java.lang.Object)transaction);
                    if (!task.cancel()) {
                        logger.warn("Service: " + this.connectionFactoryManager.service.getName() + " made an unsuccessful attempt to cancel an interrupt for transaction: " + (java.lang.Object)transaction + ". This can happen either because the interrupt was not scheduled yet or because it already fired.");
                    } else {
                        logger.info("Service: " + this.connectionFactoryManager.service.getName() + " successfully removed scheduled interrupt for transaction: " + (java.lang.Object)transaction);
                    }
                } else {
                    logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " did not schedule an interrupt for transaction: " + (java.lang.Object)transaction);
                }
            } else {
                logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " resource: " + this.connectionResourceMap.get((java.lang.Object)transaction) + " specified invalid timeout of " + seconds + "s. Aborting attempt to interrupt transaction: " + (java.lang.Object)transaction);
            }
            return;
        }
        TimerTask interruptTask = new TimerTask(){

            public void run() {
                try {
                    if (transaction != null) {
                        int txStatus = transaction.getStatus();
                        logger.debug("Service: " + ConnectionFactoryManagerPeerImpl.this.connectionFactoryManager.service.getName() + " resource: " + ConnectionFactoryManagerPeerImpl.this.connectionResourceMap.get((java.lang.Object)transaction) + " has timed out. Attempting to interrupt transaction: " + (java.lang.Object)transaction + " with status: " + txStatus);
                        ConnectionFactoryManagerPeerImpl.this.killProcess(transaction);
                    } else {
                        logger.info("Service: " + ConnectionFactoryManagerPeerImpl.this.connectionFactoryManager.service.getName() + " resource: " + ConnectionFactoryManagerPeerImpl.this.connectionResourceMap.get((java.lang.Object)transaction) + " cannot interrupt transaction: null");
                    }
                }
                catch (SystemException e) {
                    throw new UndeclaredThrowableException((Throwable)e, "Unexpected exception while cleaning up timed out resource");
                }
            }
        };
        if (this.interruptTaskMap.containsKey((java.lang.Object)transaction)) {
            logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " attempting to remove scheduled interrupt for transaction: " + (java.lang.Object)transaction + " because a new timeout of " + seconds + "s has been set on current instance.");
            TimerTask task = (TimerTask)this.interruptTaskMap.remove((java.lang.Object)transaction);
            if (!task.cancel()) {
                logger.warn("Service: " + this.connectionFactoryManager.service.getName() + " made an unsuccessful attempt to cancel an interrupt for transaction: " + (java.lang.Object)transaction + ". This can happen either because the interrupt was not scheduled yet or because it already fired.");
            } else {
                logger.debug("Service: " + this.connectionFactoryManager.service.getName() + " successfully removed scheduled interrupt for transaction: " + (java.lang.Object)transaction);
            }
        }
        try {
            interruptTimer.schedule(interruptTask, seconds * 1000);
        }
        catch (IllegalStateException ise) {
            logger.info("Service: " + this.connectionFactoryManager.service.getName() + " timer: " + interruptTimer + " is in a cancelled state due to prior errors or task completions, creating a new timer for further scheduling of interrupts.");
            interruptTimer = new Timer(true);
            interruptTimer.schedule(interruptTask, seconds * 1000);
        }
        this.interruptTaskMap.put(transaction, interruptTask);
        logger.info("Service: " + this.connectionFactoryManager.service.getName() + " successfully scheduled an interrupt for transaction: " + (java.lang.Object)transaction + " after " + seconds + "s.");
    }

    public static class Factory
    implements ConnectionFactoryManagerPeer.Factory {
        public ConnectionFactoryManagerPeer create(ConnectionFactoryManager connectionFactoryManager) {
            return new ConnectionFactoryManagerPeerImpl(connectionFactoryManager);
        }
    }

}