| /* |
| * 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.connectors; |
| |
| import com.sun.enterprise.connectors.authentication.RuntimeSecurityMap; |
| import com.sun.enterprise.connectors.module.ConnectorApplication; |
| import com.sun.enterprise.deployment.ConnectorDescriptor; |
| import com.sun.logging.LogDomains; |
| import org.glassfish.connectors.config.ResourceAdapterConfig; |
| import org.glassfish.resourcebase.resources.api.PoolInfo; |
| import org.glassfish.resourcebase.resources.api.ResourceInfo; |
| import jakarta.resource.spi.ManagedConnectionFactory; |
| import jakarta.validation.Validator; |
| import java.util.*; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import java.util.concurrent.atomic.AtomicLong; |
| import java.util.concurrent.*; |
| |
| |
| /** |
| * This is an registry class which holds various objects in hashMaps, |
| * hash tables, and vectors. These objects are updated and queried |
| * during various funtionalities of rar deployment/undeployment, resource |
| * creation/destruction |
| * Ex. of these objects are ResourcesAdapter instances, security maps for |
| * pool managed connection factories. |
| * It follows singleton pattern. i.e only one instance at any point of time. |
| * |
| * @author Binod P.G and Srikanth P |
| */ |
| |
| public class ConnectorRegistry { |
| |
| static final Logger _logger = LogDomains.getLogger(ConnectorRegistry.class, LogDomains.RSR_LOGGER); |
| |
| protected static final ConnectorRegistry connectorRegistryInstance = new ConnectorRegistry(); |
| |
| /** |
| * <code>resourceAdapters</code> keeps track of all active resource |
| * adapters in the connector runtime. |
| * String:resourceadapterName Vs ActiveResourceAdapter |
| */ |
| protected final Map<String, ActiveResourceAdapter> resourceAdapters; |
| |
| protected final Map<PoolInfo, PoolMetaData> factories; |
| protected final Map<String, ResourceAdapterConfig> resourceAdapterConfig; |
| protected final Map<String, ConnectorApplication> rarModules; |
| protected final Map<String, Validator> beanValidators; |
| protected final ConcurrentMap<ResourceInfo, AtomicLong> resourceInfoVersion; |
| protected final Set<ResourceInfo> resourceInfos; |
| protected final Set<PoolInfo> transparentDynamicReconfigPools; |
| protected final Map<String, Object> locks; |
| |
| /** |
| * Return the ConnectorRegistry instance |
| * |
| * @return ConnectorRegistry instance which is a singleton |
| */ |
| public static ConnectorRegistry getInstance() { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine("returning the connector registry"); |
| } |
| return connectorRegistryInstance; |
| } |
| |
| /** |
| * Protected constructor. |
| * It is protected as it follows singleton pattern. |
| */ |
| |
| protected ConnectorRegistry() { |
| resourceAdapters = Collections.synchronizedMap(new HashMap<String, ActiveResourceAdapter>()); |
| factories = Collections.synchronizedMap(new HashMap<PoolInfo, PoolMetaData>()); |
| resourceAdapterConfig = Collections.synchronizedMap(new HashMap<String, ResourceAdapterConfig>()); |
| rarModules = Collections.synchronizedMap(new HashMap<String, ConnectorApplication>()); |
| beanValidators = Collections.synchronizedMap(new HashMap<String, Validator>()); |
| resourceInfoVersion = new ConcurrentHashMap<ResourceInfo, AtomicLong>(); |
| resourceInfos = new HashSet<ResourceInfo>(); |
| transparentDynamicReconfigPools = new HashSet<PoolInfo>(); |
| locks = new HashMap<String, Object>(); |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, "initialized the connector registry"); |
| } |
| } |
| |
| /** |
| * Adds the object implementing ActiveResourceAdapter |
| * interface to the registry. |
| * |
| * @param rarModuleName RarName which is the key |
| * @param rar ActiveResourceAdapter instance which is the value. |
| */ |
| |
| public void addActiveResourceAdapter(String rarModuleName, |
| ActiveResourceAdapter rar) { |
| resourceAdapters.put(rarModuleName, rar); |
| if (_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, |
| "Added the active resource adapter to connector registry", |
| rarModuleName); |
| } |
| } |
| |
| /** |
| * get the version counter of a resource info |
| * @param resourceInfo resource-name |
| * @return version counter. {@code -1L} if the resource is invalid |
| */ |
| public long getResourceInfoVersion(ResourceInfo resourceInfo) { |
| AtomicLong version = resourceInfoVersion.get(resourceInfo); |
| if (version == null) { |
| // resource is no longer valid |
| return -1L; |
| } else { |
| return version.get(); |
| } |
| } |
| |
| /** |
| * Update version information for a resource. |
| * @param resourceInfo resource info to be updated. |
| * @return new version couter |
| */ |
| public long updateResourceInfoVersion(ResourceInfo resourceInfo) { |
| AtomicLong version = resourceInfoVersion.get(resourceInfo); |
| if (version == null) { |
| AtomicLong newVersion = new AtomicLong(); |
| version = resourceInfoVersion.putIfAbsent(resourceInfo, newVersion); |
| if (version == null) { |
| version = newVersion; |
| } |
| } |
| return version.incrementAndGet(); |
| } |
| |
| /** |
| * remove and invalidate factories (proxy to actual factory) using the resource. |
| * @param resourceInfo resource-name |
| * @return boolean indicating whether the factories will get invalidated |
| */ |
| public boolean removeResourceFactories(ResourceInfo resourceInfo){ |
| resourceInfoVersion.remove(resourceInfo); |
| return false; // we actually don't know if there are any resource factories instantiated. |
| } |
| |
| /** |
| * Add resourceInfo that is deployed for book-keeping purposes. |
| * @param resourceInfo Resource being deployed. |
| */ |
| public void addResourceInfo(ResourceInfo resourceInfo){ |
| if(resourceInfo != null){ |
| synchronized (resourceInfos){ |
| resourceInfos.add(resourceInfo); |
| } |
| updateResourceInfoVersion(resourceInfo); |
| } |
| } |
| |
| /** |
| * Remove ResourceInfo from registry. Called when resource is disabled/undeployed. |
| * @param resourceInfo ResourceInfo |
| * @return boolean indicating whether resource exists and removed. |
| */ |
| public boolean removeResourceInfo(ResourceInfo resourceInfo){ |
| boolean removed = false; |
| if(resourceInfo != null){ |
| synchronized (resourceInfos){ |
| removed = resourceInfos.remove(resourceInfo); |
| } |
| resourceInfoVersion.remove(resourceInfo); |
| } |
| return removed; |
| } |
| |
| /** |
| * indicates whether the resource is deployed (enabled) |
| * @param resourceInfo resource-info |
| * @return boolean indicating whether the resource is deployed. |
| */ |
| public boolean isResourceDeployed(ResourceInfo resourceInfo){ |
| boolean isDeployed = false; |
| if(resourceInfo != null){ |
| isDeployed = resourceInfos.contains(resourceInfo); |
| } |
| return isDeployed; |
| } |
| |
| /** |
| * Add PoolInfo that has transparent-dynamic-reconfiguration enabled . |
| * @param poolInfo Pool being deployed. |
| */ |
| public void addTransparentDynamicReconfigPool(PoolInfo poolInfo){ |
| if(poolInfo != null){ |
| synchronized (transparentDynamicReconfigPools){ |
| transparentDynamicReconfigPools.add(poolInfo); |
| } |
| } |
| } |
| |
| /** |
| * Remove ResourceInfo from registry. Called when resource is disabled/undeployed. |
| * @param poolInfo poolInfo |
| * @return boolean indicating whether the pool exists and removed. |
| */ |
| public boolean removeTransparentDynamicReconfigPool(PoolInfo poolInfo){ |
| boolean removed = false; |
| if(poolInfo != null){ |
| synchronized (transparentDynamicReconfigPools){ |
| removed = transparentDynamicReconfigPools.remove(poolInfo); |
| } |
| } |
| return removed; |
| } |
| |
| /** |
| * indicates whether the pool has transparent-dynamic-reconfiguration property enabled |
| * @param poolInfo poolInfo |
| * @return boolean false if pool is not deployed |
| */ |
| public boolean isTransparentDynamicReconfigPool(PoolInfo poolInfo){ |
| boolean isDeployed = false; |
| if(poolInfo != null){ |
| isDeployed = transparentDynamicReconfigPools.contains(poolInfo); |
| } |
| return isDeployed; |
| } |
| |
| /** |
| * Removes the object implementing ActiveResourceAdapter |
| * interface from the registry. |
| * This method is called whenever an active connector module |
| * is removed from the Connector runtime. [eg. undeploy/recreate etc] |
| * |
| * @param rarModuleName RarName which is the key |
| * @return true if successfully removed |
| * false if deletion fails. |
| */ |
| |
| public boolean removeActiveResourceAdapter(String rarModuleName) { |
| Object o = resourceAdapters.remove(rarModuleName); |
| |
| if (o == null) { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine("Failed to remove the resource adapter from connector registry" + |
| rarModuleName); |
| } |
| return false; |
| } else { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine("removed the active resource adapter from connector registry" + |
| rarModuleName); |
| } |
| return true; |
| } |
| } |
| |
| /** |
| * Retrieves the object implementing ActiveResourceAdapter interface |
| * from the registry. Key is the rarName. |
| * |
| * @param rarModuleName Rar name. It is the key |
| * @return object implementing ActiveResourceAdapter interface |
| */ |
| |
| public ActiveResourceAdapter getActiveResourceAdapter( |
| String rarModuleName) { |
| if (rarModuleName != null) { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine( |
| "returning/found the resource adapter from connector registry " + |
| rarModuleName); |
| } |
| return resourceAdapters.get(rarModuleName); |
| } else { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine( |
| "resource-adapter not found in connector registry. Returning null"); |
| } |
| return null; |
| } |
| } |
| |
| /** |
| * lock object that will be used by ResourceAdapterAdminService |
| * to avoid multiple calls to create ActiveRA for same resource-adapter |
| * @param rarName resource-adapter name |
| * @return lock object for the resource-adapter |
| */ |
| public Object getLockObject(String rarName) { |
| if (rarName == null) { |
| return null; |
| } |
| Object lock; |
| synchronized (locks) { |
| lock = locks.get(rarName); |
| if (lock == null) { |
| lock = new Object(); |
| locks.put(rarName, lock); |
| if (_logger.isLoggable(Level.FINE)) { |
| _logger.fine("added lock-object [ " + lock + " ] for rar : " + rarName); |
| } |
| } |
| } |
| return lock; |
| } |
| |
| /** |
| * removes the lock-object used for creating the ActiveRA for a particular RAR |
| * @param rarName resource-adapter |
| */ |
| public void removeLockObject(String rarName) { |
| if (rarName == null) { |
| return; |
| } |
| synchronized (locks) { |
| Object lock = locks.remove(rarName); |
| if (_logger.isLoggable(Level.FINE)) { |
| _logger.fine("removed lock-object [ " + lock + " ] for rar : " + rarName); |
| } |
| } |
| } |
| |
| |
| /** |
| * Adds the bean validator to the registry. |
| * |
| * @param rarModuleName RarName which is the key |
| * @param validator to be added to registry |
| */ |
| public void addBeanValidator(String rarModuleName, Validator validator){ |
| beanValidators.put(rarModuleName, validator); |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, "Added the bean validator for RAR [ "+rarModuleName+" ] to connector registry"); |
| } |
| } |
| |
| /** |
| * Retrieves the bean validator of a resource-adapter |
| * from the registry. Key is the rarName. |
| * |
| * @param rarModuleName Rar name. It is the key |
| * @return bean validator |
| */ |
| public Validator getBeanValidator(String rarModuleName){ |
| if (rarModuleName != null) { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine( |
| "returning/found the validator for RAR [ "+rarModuleName+" ] from connector registry"); |
| } |
| return beanValidators.get(rarModuleName); |
| } else { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine( |
| "bean validator for RAR not found in connector registry.Returning null"); |
| } |
| return null; |
| } |
| } |
| |
| /** |
| * Removes the bean validator of a resource-adapter |
| * from the registry. |
| * This method is called whenever an active connector module |
| * is removed from the Connector runtime. [eg. undeploy/recreate etc] |
| * |
| * @param rarModuleName RarName which is the key |
| * @return true if successfully removed |
| * false if deletion fails. |
| */ |
| public boolean removeBeanValidator(String rarModuleName) { |
| Object o = beanValidators.remove(rarModuleName); |
| |
| if (o == null) { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine("Failed to remove the bean validator for RAR [ "+rarModuleName+" ] from connector registry"); |
| } |
| return false; |
| } else { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine("removed the active bean validator for RAR [ "+rarModuleName +" ] from connector registry"); |
| } |
| return true; |
| } |
| } |
| |
| /** |
| * Checks if the MCF pertaining to the pool is instantiated and present |
| * in the registry. Each pool has its own MCF instance. |
| * |
| * @param poolInfo Name of the pool |
| * @return true if the MCF is found. |
| * false if MCF is not found |
| */ |
| |
| |
| public boolean isMCFCreated(PoolInfo poolInfo) { |
| boolean created = factories.containsKey(poolInfo); |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine("isMCFCreated " + poolInfo + " - " + created); |
| } |
| return created; |
| } |
| |
| |
| /** |
| * Remove MCF instance pertaining to the poolName from the registry. |
| * |
| * @param poolInfo Name of the pool |
| * @return true if successfully removed. |
| * false if removal fails. |
| */ |
| |
| public boolean removeManagedConnectionFactory(PoolInfo poolInfo) { |
| if (factories.remove(poolInfo) == null) { |
| if (_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, |
| "Failed to remove the MCF from connector registry.", poolInfo); |
| } |
| return false; |
| } else { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine("removeMCF " + poolInfo + " - " + !factories.containsKey(poolInfo)); |
| } |
| return true; |
| } |
| } |
| |
| /** |
| * Add MCF instance pertaining to the poolName to the registry. |
| * |
| * @param poolInfo Name of the pool |
| * @param pmd MCF instance to be added. |
| */ |
| public void addManagedConnectionFactory(PoolInfo poolInfo, |
| PoolMetaData pmd) { |
| factories.put(poolInfo, pmd); |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.fine("Added MCF to connector registry for: " + poolInfo); |
| } |
| } |
| |
| /** |
| * Retrieve MCF instance pertaining to the poolName from the registry. |
| * |
| * @param poolInfo Name of the pool |
| * @return factory MCF instance retrieved. |
| */ |
| |
| |
| public ManagedConnectionFactory getManagedConnectionFactory( |
| PoolInfo poolInfo) { |
| if (poolInfo != null) { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, |
| "Returning the MCF from connector registry.", poolInfo); |
| } |
| |
| PoolMetaData pmd = factories.get(poolInfo); |
| if (pmd != null) { |
| return pmd.getMCF(); |
| } |
| |
| } |
| return null; |
| } |
| |
| /** |
| * Checks whether the rar is already deployed i.e registered with |
| * connector registry |
| * |
| * @param rarModuleName rar Name. |
| * @return true if rar is registered |
| * false if rar is not registered. |
| */ |
| |
| public boolean isRegistered(String rarModuleName) { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, |
| "Checking for MCF presence in connector registry.", rarModuleName); |
| } |
| return resourceAdapters.containsKey(rarModuleName); |
| } |
| |
| /** |
| * Gets the connector descriptor pertaining the rar |
| * |
| * @param rarModuleName rarName |
| * @return ConnectorDescriptor which represents the ra.xml |
| */ |
| |
| public ConnectorDescriptor getDescriptor(String rarModuleName) { |
| ActiveResourceAdapter ar = null; |
| if (rarModuleName != null) { |
| ar = resourceAdapters.get(rarModuleName); |
| } |
| if (ar != null) { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, |
| "Found/returing Connector descriptor in connector registry.", |
| rarModuleName); |
| } |
| return ar.getDescriptor(); |
| } else { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, |
| "Couldnot find Connector descriptor in connector registry.", |
| rarModuleName); |
| } |
| return null; |
| } |
| } |
| |
| /** Gets the runtime equivalent of policies enforced by the Security Maps |
| * pertaining to a pool from the Pool's Meta Data. |
| * @param poolInfo pool information |
| * @return runtimeSecurityMap in the form of HashMap of |
| * HashMaps (user and groups). |
| * @see SecurityMapUtils.processSecurityMaps( SecurityMap[]) |
| */ |
| |
| |
| public RuntimeSecurityMap getRuntimeSecurityMap(PoolInfo poolInfo) { |
| if(poolInfo != null) { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, "Returing the security map from connector registry.", poolInfo); |
| } |
| PoolMetaData pmd = factories.get(poolInfo); |
| return pmd.getRuntimeSecurityMap(); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Get the resource adapter config properties object registered with |
| * registry against the rarName. |
| * |
| * @param rarName Name of the rar |
| * @return ResourceAdapter configuration object |
| */ |
| |
| public ResourceAdapterConfig getResourceAdapterConfig(String rarName) { |
| if (rarName != null) { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, |
| "Returing the resourceadapter Config from registry.", rarName); |
| } |
| return resourceAdapterConfig.get(rarName); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Add the resource adapter config properties object to registry |
| * against the rarName. |
| * |
| * @param rarName Name of the rar |
| * @param raConfig ResourceAdapter configuration object |
| */ |
| |
| public void addResourceAdapterConfig(String rarName, |
| ResourceAdapterConfig raConfig) { |
| if (rarName != null) { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, |
| "Adding the resourceAdapter Config to connector registry.", |
| rarName); |
| } |
| resourceAdapterConfig.put(rarName, raConfig); |
| } |
| } |
| |
| /** |
| * Remove the resource adapter config properties object from registry |
| * |
| * @param rarName Name of the rar |
| * @return true if successfully deleted |
| * false if deletion fails |
| */ |
| |
| public boolean removeResourceAdapterConfig(String rarName) { |
| if (resourceAdapterConfig.remove(rarName) == null) { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, |
| "failed to remove the resourceAdapter config from registry.", |
| rarName); |
| } |
| return false; |
| } else { |
| if(_logger.isLoggable(Level.FINE)) { |
| _logger.log(Level.FINE, |
| "Removed the resourceAdapter config map from registry.", |
| rarName); |
| } |
| return true; |
| } |
| } |
| |
| /** |
| * Returns all Active Resource Adapters in the connector runtime. |
| * |
| * @return All active resource adapters in the connector runtime |
| */ |
| public ActiveResourceAdapter[] getAllActiveResourceAdapters() { |
| ActiveResourceAdapter araArray[] = new ActiveResourceAdapter[this.resourceAdapters.size()]; |
| return this.resourceAdapters.values().toArray(araArray); |
| } |
| |
| public PoolMetaData getPoolMetaData(PoolInfo poolInfo) { |
| return factories.get(poolInfo); |
| } |
| |
| /** |
| * register a connector application (rarModule) with the registry |
| * @param rarModule resource-adapter module |
| */ |
| public void addConnectorApplication(ConnectorApplication rarModule){ |
| rarModules.put(rarModule.getModuleName(), rarModule); |
| } |
| |
| /** |
| * retrieve a connector application (rarModule) from the registry |
| * @param rarName resource-adapter name |
| * @return ConnectorApplication app |
| */ |
| public ConnectorApplication getConnectorApplication(String rarName){ |
| return rarModules.get(rarName); |
| } |
| |
| /** |
| * remove a connector application (rarModule) from the registry |
| * @param rarName resource-adapter module |
| */ |
| public void removeConnectorApplication(String rarName){ |
| rarModules.remove(rarName); |
| } |
| |
| /** |
| * get the list of resource-adapters that support this message-listener-type |
| * @param messageListener message-listener class-name |
| * @return List of resource-adapters |
| */ |
| public List<String> getConnectorsSupportingMessageListener(String messageListener){ |
| |
| List<String> rars = new ArrayList<String>(); |
| for(ActiveResourceAdapter ara : resourceAdapters.values()){ |
| ConnectorDescriptor desc = ara.getDescriptor(); |
| if(desc.getInBoundDefined()){ |
| if(desc.getInboundResourceAdapter().getMessageListener(messageListener) != null){ |
| rars.add(ara.getModuleName()); |
| } |
| } |
| } |
| return rars; |
| } |
| } |