| /* |
| * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| package com.sun.enterprise.resource; |
| |
| import com.sun.enterprise.resource.allocator.ResourceAllocator; |
| import com.sun.enterprise.resource.allocator.LocalTxConnectorAllocator; |
| import com.sun.enterprise.connectors.ConnectorRuntime; |
| import com.sun.logging.LogDomains; |
| import com.sun.appserv.connectors.internal.api.PoolingException; |
| import com.sun.enterprise.transaction.spi.TransactionalResource; |
| |
| import jakarta.resource.spi.ConnectionEventListener; |
| import javax.security.auth.Subject; |
| import javax.transaction.xa.XAResource; |
| import jakarta.transaction.Transaction; |
| import java.util.logging.Logger; |
| import java.util.logging.Level; |
| |
| |
| /** |
| * ResourceHandle encapsulates a resource connection. |
| * Equality on the handle is based on the id field |
| * |
| * @author Tony Ng |
| */ |
| public class ResourceHandle implements |
| com.sun.appserv.connectors.internal.api.ResourceHandle, TransactionalResource { |
| |
| // unique ID for resource handles |
| static private long idSequence; |
| |
| private long id; |
| private ClientSecurityInfo info; |
| private Object resource; // represents MC |
| private ResourceSpec spec; |
| private XAResource xares; |
| private Object usercon; // represents connection-handle to user |
| private ResourceAllocator alloc; |
| private Object instance; // the component instance holding this resource |
| private int shareCount; // sharing within a component (XA only) |
| private boolean supportsXAResource = false; |
| |
| private volatile boolean busy; |
| |
| private Subject subject = null; |
| |
| private ResourceState state = null; |
| private ConnectionEventListener listener = null; |
| |
| private boolean enlistmentSuspended = false; |
| |
| private boolean supportsLazyEnlistment_ = false; |
| private boolean supportsLazyAssoc_ = false; |
| |
| private static Logger logger = LogDomains.getLogger(ResourceHandle.class, LogDomains.RSR_LOGGER); |
| |
| public final Object lock = new Object(); |
| private long lastValidated; //holds the latest time at which the connection was validated. |
| private int usageCount; //holds the no. of times the handle(connection) is used so far. |
| private int partition; |
| private boolean isDestroyByLeakTimeOut = false; |
| |
| static private long getNextId() { |
| synchronized (ResourceHandle.class) { |
| idSequence++; |
| return idSequence; |
| } |
| } |
| private boolean markedReclaim = false; |
| |
| public ResourceHandle(Object resource, |
| ResourceSpec spec, |
| ResourceAllocator alloc, |
| ClientSecurityInfo info) { |
| this.id = getNextId(); |
| this.spec = spec; |
| this.info = info; |
| this.resource = resource; |
| this.alloc = alloc; |
| |
| if (alloc instanceof LocalTxConnectorAllocator) |
| supportsXAResource = false; |
| else |
| supportsXAResource = true; |
| |
| if (resource instanceof |
| jakarta.resource.spi.LazyEnlistableManagedConnection) { |
| supportsLazyEnlistment_ = true; |
| } |
| |
| if (resource instanceof |
| jakarta.resource.spi.DissociatableManagedConnection) { |
| supportsLazyAssoc_ = true; |
| } |
| } |
| |
| /* public ResourceHandle(Object resource, |
| ResourceSpec spec, |
| ResourceAllocator alloc, |
| ClientSecurityInfo info, |
| boolean supportsXA) { |
| this.id = getNextId(); |
| this.spec = spec; |
| this.info = info; |
| this.resource = resource; |
| this.alloc = alloc; |
| |
| supportsXAResource = supportsXA; |
| |
| if (resource instanceof |
| jakarta.resource.spi.LazyEnlistableManagedConnection) { |
| supportsLazyEnlistment_ = true; |
| } |
| |
| if (resource instanceof |
| jakarta.resource.spi.DissociatableManagedConnection) { |
| supportsLazyAssoc_ = true; |
| } |
| } */ |
| |
| |
| /** |
| * Does this resource need enlistment to transaction manager? |
| */ |
| public boolean isTransactional() { |
| return alloc.isTransactional(); |
| } |
| |
| /** |
| * To check whether lazy enlistment is suspended or not.<br> |
| * If true, TM will not do enlist/lazy enlist. |
| * |
| * @return boolean |
| */ |
| public boolean isEnlistmentSuspended() { |
| return enlistmentSuspended; |
| } |
| |
| public void setEnlistmentSuspended(boolean enlistmentSuspended) { |
| this.enlistmentSuspended = enlistmentSuspended; |
| } |
| |
| public void markForReclaim(boolean reclaim) { |
| this.markedReclaim = reclaim; |
| } |
| |
| /** |
| * To check if the resourceHandle is marked for leak reclaim or not. <br> |
| * |
| * @return boolean |
| */ |
| public boolean isMarkedForReclaim() { |
| return markedReclaim; |
| } |
| |
| public boolean supportsXA() { |
| return supportsXAResource; |
| } |
| |
| public ResourceAllocator getResourceAllocator() { |
| return alloc; |
| } |
| |
| public Object getResource() { |
| return resource; |
| } |
| |
| public ClientSecurityInfo getClientSecurityInfo() { |
| return info; |
| } |
| |
| public void setResourceSpec(ResourceSpec spec) { |
| this.spec = spec; |
| } |
| |
| public ResourceSpec getResourceSpec() { |
| return spec; |
| } |
| |
| public XAResource getXAResource() { |
| return xares; |
| } |
| |
| public Object getUserConnection() { |
| return usercon; |
| } |
| |
| public void setComponentInstance(Object instance) { |
| this.instance = instance; |
| } |
| |
| public void closeUserConnection() throws PoolingException { |
| getResourceAllocator().closeUserConnection(this); |
| } |
| |
| public Object getComponentInstance() { |
| return instance; |
| } |
| |
| public long getId() { |
| return id; |
| } |
| |
| public void fillInResourceObjects(Object userConnection, |
| XAResource xaRes) { |
| if (userConnection != null) usercon = userConnection; |
| |
| if (xaRes != null) { |
| if (logger.isLoggable(Level.FINEST)) { |
| //When Log level is Finest, XAResourceWrapper is used to log |
| //all XA interactions - Don't wrap XAResourceWrapper if it is |
| //already wrapped |
| if ((xaRes instanceof XAResourceWrapper) || |
| (xaRes instanceof ConnectorXAResource)) { |
| this.xares = xaRes; |
| } else { |
| this.xares = new XAResourceWrapper(xaRes); |
| } |
| } else { |
| this.xares = xaRes; |
| } |
| } |
| |
| } |
| |
| // For XA-capable connections, multiple connections within a |
| // component are collapsed into one. shareCount keeps track of |
| // the number of additional shared connections |
| public void incrementCount() { |
| shareCount++; |
| } |
| |
| public void decrementCount() { |
| if (shareCount == 0) { |
| throw new IllegalStateException("shareCount cannot be negative"); |
| } else { |
| shareCount--; |
| } |
| } |
| |
| public int getShareCount() { |
| return shareCount; |
| } |
| |
| public void setSubject(Subject subject) { |
| this.subject = subject; |
| } |
| |
| public Subject getSubject() { |
| return subject; |
| } |
| |
| public boolean equals(Object other) { |
| if (other == null) return false; |
| if (other instanceof ResourceHandle) { |
| return this.id == (((ResourceHandle) other).id); |
| } |
| return false; |
| } |
| |
| public int hashCode() { |
| return Long.valueOf(id).hashCode(); |
| } |
| |
| public String toString() { |
| return String.valueOf(id); |
| } |
| |
| private boolean connectionErrorOccurred = false; |
| |
| public void setConnectionErrorOccurred() { |
| connectionErrorOccurred = true; |
| } |
| |
| public boolean hasConnectionErrorOccurred() { |
| return connectionErrorOccurred; |
| } |
| |
| public void setResourceState(ResourceState state) { |
| this.state = state; |
| } |
| |
| public ResourceState getResourceState() { |
| return state; |
| } |
| |
| public void setListener(ConnectionEventListener l) { |
| this.listener = l; |
| } |
| |
| public ConnectionEventListener getListener() { |
| return listener; |
| } |
| |
| public boolean isShareable() { |
| return alloc.shareableWithinComponent(); |
| } |
| |
| public void destroyResource() { |
| throw new UnsupportedOperationException("Transaction is not supported yet"); |
| } |
| |
| public boolean isEnlisted() { |
| return state != null && state.isEnlisted(); |
| } |
| |
| public long getLastValidated() { |
| return lastValidated; |
| } |
| |
| public void setLastValidated(long lastValidated) { |
| this.lastValidated = lastValidated; |
| } |
| |
| public int getUsageCount() { |
| return usageCount; |
| } |
| |
| public void incrementUsageCount() { |
| usageCount++; |
| } |
| |
| public int getPartition() { |
| return partition; |
| } |
| |
| public void setPartition(int partition) { |
| this.partition = partition; |
| } |
| |
| public String getName() { |
| return spec.getResourceId(); |
| } |
| |
| public boolean supportsLazyEnlistment() { |
| return supportsLazyEnlistment_; |
| } |
| |
| public boolean supportsLazyAssociation() { |
| return supportsLazyAssoc_; |
| } |
| |
| public void enlistedInTransaction(Transaction tran) throws IllegalStateException { |
| ConnectorRuntime.getRuntime().getPoolManager().resourceEnlisted(tran, this); |
| } |
| |
| public void setBusy(boolean isBusy){ |
| busy = isBusy; |
| } |
| |
| public boolean isBusy(){ |
| return busy; |
| } |
| |
| public boolean getDestroyByLeakTimeOut(){ |
| return isDestroyByLeakTimeOut; |
| } |
| |
| public void setDestroyByLeakTimeOut(boolean isDestroyByLeakTimeOut){ |
| this.isDestroyByLeakTimeOut = isDestroyByLeakTimeOut; |
| } |
| } |