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

com.sun.enterprise.connectors.inbound.InboundRecoveryHandler Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2012 Oracle and/or its affiliates. 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_1_1.html
 * or packager/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 packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [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.
 */
// Portions Copyright [2016-2021] [Payara Foundation]

package com.sun.enterprise.connectors.inbound;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.resource.spi.ActivationSpec;
import javax.transaction.xa.XAResource;

import com.sun.appserv.connectors.internal.api.ConnectorConstants;
import com.sun.appserv.connectors.internal.api.ConnectorRuntime;
import com.sun.appserv.connectors.internal.api.ConnectorRuntimeException;
import com.sun.appserv.connectors.internal.api.ConnectorsUtil;
import com.sun.enterprise.config.serverbeans.Application;
import com.sun.enterprise.config.serverbeans.Applications;
import com.sun.enterprise.config.serverbeans.ConfigBeansUtilities;
import com.sun.enterprise.connectors.ConnectorRegistry;
import com.sun.enterprise.connectors.service.ConnectorAdminServiceUtils;
import com.sun.enterprise.connectors.util.RARUtils;
import com.sun.enterprise.connectors.util.ResourcesUtil;
import com.sun.enterprise.connectors.util.SetMethodAction;
import com.sun.enterprise.deployment.BundleDescriptor;
import com.sun.enterprise.deployment.EjbBundleDescriptor;
import com.sun.enterprise.deployment.EjbDescriptor;
import com.sun.enterprise.deployment.EjbMessageBeanDescriptor;
import com.sun.enterprise.transaction.spi.RecoveryResourceHandler;
import com.sun.logging.LogDomains;
import org.glassfish.internal.data.ApplicationInfo;
import org.glassfish.internal.data.ApplicationRegistry;
import org.jvnet.hk2.annotations.Service;


/**
 * Recovery handler for Inbound transactions
 *
 * @author Jagadish Ramu
 */
@Service
public class InboundRecoveryHandler implements RecoveryResourceHandler {

    @Inject
    private Applications deployedApplications;

    @Inject
    private ApplicationRegistry appsRegistry;

    @Inject
    private Provider connectorRuntimeProvider;
    
    @Inject
    private ConfigBeansUtilities configBeansUtilities;
    

    private static Logger _logger = LogDomains.getLogger(InboundRecoveryHandler.class, LogDomains.RSR_LOGGER);

    /**
     * {@inheritDoc}
     */
    public void loadXAResourcesAndItsConnections(List xaresList, List connList) {
        Vector xaResources = new Vector();
        recoverInboundTransactions(xaResources);
    }

    /**
     * {@inheritDoc}
     */
    public void closeConnections(List connList) {
        // do nothing
    }

    private void recoverInboundTransactions(List xaresList) {

        List applications = deployedApplications.getApplications();

        try {
            _logger.log(Level.INFO, "Recovery of Inbound Transactions started.");

            if (applications.size() == 0) {
                _logger.log(Level.FINE, "No applications deployed.");
                return;
            }
            // List of CMT enabled MDB descriptors on the application server instance.
            List xaEnabledMDBList = new ArrayList();

            //Done so as to initialize connectors-runtime before loading inbound active RA. need a better way ?
            ConnectorRuntime cr = connectorRuntimeProvider.get();

            for (Application application : applications) {
                Vector ejbDescVec = getEjbDescriptors(application, appsRegistry);
                for (int j = 0; j < ejbDescVec.size(); j++) {
                    EjbDescriptor desc = (EjbDescriptor) ejbDescVec.elementAt(j);
                    // If EjbDescriptor is an instance of a CMT enabled MDB descriptor,
                    // add it to the list of xaEnabledMDBList.
                    if (desc instanceof EjbMessageBeanDescriptor &&
                            desc.getTransactionType().
                                    equals(EjbDescriptor.CONTAINER_TRANSACTION_TYPE)) {
                        xaEnabledMDBList.add(desc);
                        _logger.log(Level.FINE, "Found a CMT MDB: "
                                + desc.getEjbClassName());
                    }
                }
            }

            if (xaEnabledMDBList.size() == 0) {
                _logger.log(Level.FINE, "Found no CMT MDBs in all applications");
                return;
            }

            ConnectorRegistry creg = ConnectorRegistry.getInstance();

            // for each RA (key in the map) get the list (value) of MDB Descriptors
            Map> mappings = createRAEjbMapping(xaEnabledMDBList);

            //For each RA
            for (Map.Entry entry : mappings.entrySet()) {

                String raMid = (String) entry.getKey();
                List respectiveDesc = mappings.get(raMid);

                try {
                    createActiveResourceAdapter(raMid);
                } catch (Exception ex) {
                    _logger.log(Level.SEVERE, "error.loading.connector.resources.during.recovery", raMid);
                    if (_logger.isLoggable(Level.FINE)) {
                        _logger.log(Level.FINE, ex.toString(), ex);
                    }
                }

                ActiveInboundResourceAdapter activeInboundRA = (ActiveInboundResourceAdapter) creg
                        .getActiveResourceAdapter(raMid);

                //assert activeInboundRA instanceof ActiveInboundResourceAdapter;

                boolean isSystemJmsRA = false;
                if (ConnectorsUtil.isJMSRA(activeInboundRA.getModuleName())) {
                    isSystemJmsRA = true;
                }

                jakarta.resource.spi.ResourceAdapter resourceAdapter = activeInboundRA
                        .getResourceAdapter();
                // activationSpecList represents the ActivationSpec[] that would be
                // sent to the getXAResources() method.
                ArrayList activationSpecList = new ArrayList();

                try {
                    for (int i = 0; i < respectiveDesc.size(); i++) {
                        try {
                            // Get a MessageBeanDescriptor from respectiveDesc ArrayList
                            EjbMessageBeanDescriptor descriptor =
                                    (EjbMessageBeanDescriptor) respectiveDesc.get(i);
                            // A descriptor using 1.3 System JMS RA style properties needs
                            // to be updated J2EE 1.4 style props.
                            if (isSystemJmsRA) {
                                //XXX: Find out the pool descriptor corres to MDB and update
                                //MDBRuntimeInfo with that.
                                activeInboundRA.updateMDBRuntimeInfo(descriptor, null);
                            }

                            // Get the ActivationConfig Properties from the MDB Descriptor
                            Set activationConfigProps =
                                    RARUtils.getMergedActivationConfigProperties(descriptor);
                            // get message listener type
                            String msgListenerType = descriptor.getMessageListenerType();

                            // start resource adapter and get ActivationSpec class for
                            // the given message listener type from the ConnectorRuntime

                            ActivationSpec aspec = (ActivationSpec) (Class.forName(
                                    cr.getActivationSpecClass(raMid,
                                            msgListenerType), false,
                                    resourceAdapter.getClass().getClassLoader()).newInstance());
                            aspec.setResourceAdapter(resourceAdapter);

                            // Populate ActivationSpec class with ActivationConfig properties
                            SetMethodAction sma =
                                    new SetMethodAction(aspec, activationConfigProps);
                            sma.run();
                            activationSpecList.add(aspec);
                        } catch (Exception e) {
                            _logger.log(Level.WARNING, "error.creating.activationspec", e.getMessage());
                            if (_logger.isLoggable(Level.FINE)) {
                                _logger.log(Level.FINE, e.toString(), e);
                            }
                        }
                    }

                    // Get XA resources from RA.

                    ActivationSpec[] activationSpecArray = activationSpecList.toArray(new ActivationSpec[activationSpecList.size()]);
                    XAResource[] xar = resourceAdapter.getXAResources(activationSpecArray);

                    // Add the resources to the xaresList which is used by the RecoveryManager
                    if(xar != null){
                        for (int p = 0; p < xar.length; p++) {
                            xaresList.add(xar[p]);
                        }
                    }
                    // Catch UnsupportedOperationException if a RA does not support XA
                    // which is fine.
                } catch (UnsupportedOperationException uoex) {
                    _logger.log(Level.FINE, uoex.getMessage());
                    // otherwise catch the unexpected exception
                } catch (Exception e) {
                    _logger.log(Level.SEVERE, "exception.during.inbound.resource.acqusition", e);
                }
            }
        } catch (Exception e) {
            _logger.log(Level.SEVERE,"exception.during.inbound.recovery", e);
        }

    }

    private Vector getEjbDescriptors(Application application, ApplicationRegistry appsRegistry) {
        Vector ejbDescriptors = new Vector();

        if(ResourcesUtil.createInstance().isEnabled(application)){
            ApplicationInfo appInfo = appsRegistry.get(application.getName());
            // non java-ee apps do not have ejbs, and they dont't have Application entry, leading to NPE            
            if(appInfo != null && appInfo.isJavaEEApp()){
                com.sun.enterprise.deployment.Application app =
                        appInfo.getMetaData(com.sun.enterprise.deployment.Application.class);
                Set descriptors = app.getBundleDescriptors();
                for (BundleDescriptor descriptor : descriptors) {
                    if (descriptor instanceof EjbBundleDescriptor) {
                        EjbBundleDescriptor ejbBundleDescriptor = (EjbBundleDescriptor) descriptor;
                        Set ejbDescriptorsSet = ejbBundleDescriptor.getEjbs();
                        for (EjbDescriptor ejbDescriptor : ejbDescriptorsSet) {
                            ejbDescriptors.add(ejbDescriptor);
                        }
                    }
                }
            }else{
                //application is enabled, but still not found in app-registry
                _logger.log(Level.WARNING, "application.not.started.skipping.recovery", application.getName());
            }
        }
        return ejbDescriptors;
    }

    private Map> createRAEjbMapping(List ejbDescriptors) {

        Map> map = new HashMap>();

        for (EjbDescriptor ejbDescriptor : ejbDescriptors) {
            List ejbmdbd = new ArrayList();
            String ramid =
                    ((EjbMessageBeanDescriptor) ejbDescriptor).getResourceAdapterMid();
            if ((ramid == null) || (ramid.equalsIgnoreCase(""))) {
                ramid = ConnectorConstants.DEFAULT_JMS_ADAPTER;
            }

            // If Hashtable contains the RAMid key, get the list of MDB descriptors
            // and add the current MDB Descriptor (list[i]) to the list and put the
            // pair back into hashtable.
            // Otherwise, add the RAMid and the current MDB Descriptor to the hashtable
            if (map.containsKey(ramid)) {
                ejbmdbd = map.get(ramid);
                map.remove(ramid);
            }

            ejbmdbd.add(ejbDescriptor);
            map.put(ramid, ejbmdbd);
        }
        return map;
    }

    private void createActiveResourceAdapter(String rarModuleName) throws ConnectorRuntimeException {

        ConnectorRuntime cr = connectorRuntimeProvider.get();
        ConnectorRegistry creg = ConnectorRegistry.getInstance();

        if (creg.isRegistered(rarModuleName))
            return;

        if (ConnectorAdminServiceUtils.isEmbeddedConnectorModule(rarModuleName)) {
            cr.createActiveResourceAdapterForEmbeddedRar(rarModuleName);
        } else {
            String moduleDir ;
            if (ConnectorsUtil.belongsToSystemRA(rarModuleName)) {
                moduleDir = ConnectorsUtil.getSystemModuleLocation(rarModuleName);
            }else{
                moduleDir = configBeansUtilities.getLocation(rarModuleName);
            }
            ClassLoader loader = cr.createConnectorClassLoader(moduleDir, null, rarModuleName);
            cr.createActiveResourceAdapter(moduleDir, rarModuleName, loader);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy