/* * 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. */ /* * SunContainerHelper.java * * Created on March 12, 2003. */ package com.sun.jdo.spi.persistence.support.sqlstore.ejb; import java.util.Iterator; import java.util.ResourceBundle; import javax.ejb.EJBObject; import javax.ejb.EJBLocalObject; import javax.ejb.EJBContext; import javax.ejb.EJBException; import javax.ejb.EntityContext; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; import com.sun.enterprise.deployment.*; import com.sun.appserv.connectors.internal.api.ConnectorsUtil; //TODO Dependency on connector-internal-api needs to be removed import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.internal.data.ApplicationRegistry; import org.glassfish.internal.data.ApplicationInfo; import com.sun.ejb.Container; import com.sun.ejb.containers.EjbContainerUtil; import org.glassfish.persistence.ejb.entitybean.container.spi.CascadeDeleteNotifier; import com.sun.jdo.api.persistence.support.JDOException; import com.sun.jdo.api.persistence.support.JDOFatalInternalException; import com.sun.jdo.api.persistence.support.JDOFatalUserException; import com.sun.jdo.api.persistence.support.PersistenceManager; import com.sun.jdo.api.persistence.support.PersistenceManagerFactory; import com.sun.jdo.spi.persistence.support.sqlstore.impl.PersistenceManagerFactoryImpl; import com.sun.jdo.spi.persistence.support.sqlstore.LogHelperPersistenceManager; import com.sun.jdo.spi.persistence.support.sqlstore.utility.NumericConverter; import com.sun.jdo.spi.persistence.utility.logging.Logger; import org.glassfish.persistence.common.I18NHelper; import org.glassfish.internal.api.Globals; /** Implementation for Sun specific CMP and Container interactions as defined * by the ContainerHelper interface. * * IMPORTANT: This class extends SunTransactionHelper class. Any changes to the * TransactionHelper implementation must be done in the SunTransactionHelper. * */ public class SunContainerHelper extends SunTransactionHelper implements ContainerHelper { /** I18N message handler */ private final static ResourceBundle messages = I18NHelper.loadBundle( "com.sun.jdo.spi.persistence.support.sqlstore.Bundle", // NOI18N SunContainerHelper.class.getClassLoader()); /** The logger */ private static Logger logger = LogHelperPersistenceManager.getLogger(); /** Garantees singleton. * Registers itself during initial load */ static { CMPHelper.registerContainerHelper (new SunContainerHelper()); } /** Default constructor should not be public */ SunContainerHelper() { } /** Get a Container helper instance that will be passed unchanged to the * required methods. * This is SunContainerHelper specific code. * * The info argument is an Object array that consistes of a class to use * for the class loader and concreteImpl bean class name. * @see getEJBObject(Object, Object) * @see getEJBLocalObject(Object, Object) * @see getEJBLocalObject(Object, Object, EJBObject) * @see removeByEJBLocalObject(EJBLocalObject, Object) * @see removeByPK(Object, Object) * @param info Object with the request information that is application server * specific. * @return a Container helper instance as an Object. */ public Object getContainer(Object info) { Object[] params = (Object[])info; String appName = (String)params[0]; ServiceLocator habitat = Globals.getDefaultHabitat(); ApplicationRegistry reg = habitat.getService(ApplicationRegistry.class); ApplicationInfo appInfo = reg.get(appName); Application app = appInfo.getMetaData(Application.class); EjbDescriptor desc = app.getEjbByName((String)params[1]); return habitat.<EjbContainerUtil>getService(EjbContainerUtil.class).getContainer(desc.getUniqueId()); } /** Get an EJBObject reference for this primary key and Container helper. * This is SunContainerHelper specific code. * * @see getContainer(Object) * @param pk the primary key instance. * @param container a Container instance for the request. * @return a corresponding EJBObject instance to be used by the client. */ public EJBObject getEJBObject(Object pk, Object container) { try { return ((Container)container).getEJBObjectForPrimaryKey(pk); } catch (Exception ex) { throw new JDOFatalInternalException(ex.getMessage(), ex); } } /** Get an EJBLocalObject reference for this primary key and Container helper. * This is SunContainerHelper specific code. * * @see getContainer(Object) * @param pk the primary key instance. * @param container a helper instance for the request. * @return a corresponding EJBLocalObject instance to be used by the client. */ public EJBLocalObject getEJBLocalObject(Object pk, Object container) { try { return ((Container)container).getEJBLocalObjectForPrimaryKey(pk); } catch (Exception ex) { throw new JDOFatalInternalException(ex.getMessage(), ex); } } /** Get an EJBLocalObject reference for this primary key and Container helper, * and EJBContext of the calling bean. * Allows the container to check if this method is called during ejbRemove * that is part of a cascade-delete remove. * This is SunContainerHelper specific code. * * @see getContainer(Object) * @param pk the primary key instance. * @param container a helper instance for the request. * @param context an EJBContext of the calling bean. * @return a corresponding EJBLocalObject instance to be used by the client. */ public EJBLocalObject getEJBLocalObject(Object pk, Object container, EJBContext context) { EJBLocalObject rc = null; try { rc = ((Container)container).getEJBLocalObjectForPrimaryKey(pk, context); } catch (Exception ex) { processContainerException(ex); } return rc; } /** Remove a bean for a given EJBLocalObject and Container helper. * This is SunContainerHelper specific code. * * @see getContainer(Object) * @param ejb the EJBLocalObject for the bean to be removed. * @param container a Container instance for the request. */ public void removeByEJBLocalObject(EJBLocalObject ejb, Object container) { try { ((Container)container).removeBeanUnchecked(ejb); } catch (Exception ex) { processContainerException(ex); } } /** Remove a bean for a given primary key and Container helper. * This is SunContainerHelper specific code. * * @see getContainer(Object) * @param pk the primary key for the bean to be removed. * @param container a Container instance for the request. */ public void removeByPK(Object pk, Object container) { try { ((Container)container).removeBeanUnchecked(pk); } catch (Exception ex) { processContainerException(ex); } } /** Verify that this instance is of a valid local interface type for * a given Container helper. * This is SunContainerHelper specific code. * * @see getContainer(Object) * @param o the instance to be verified. * @param container a Container instance for the request. */ public void assertValidLocalObject(Object o, Object container) { ((Container)container).assertValidLocalObject(o); } /** Verify that this instance is of a valid remote interface type for * a given Container helper. * This is SunContainerHelper specific code. * * @see getContainer(Object) * @param o the instance to be verified. * @param container a Container instance for the request. */ public void assertValidRemoteObject(Object o, Object container) { ((Container)container).assertValidRemoteObject(o); } /** Mark the bean as already removed during cascade-delete * operation for a given EntityContext. * Called by the generated ejbRemove method before calling ejbRemove of the * related beans (via removeByEJBLocalObject) that are to be cascade-deleted. * * This is SunContainerHelper specific code. * * @param context the EntityContext of the bean beeing removed. */ public void setCascadeDeleteAfterSuperEJBRemove(EntityContext context) { try { ((CascadeDeleteNotifier)context).setCascadeDeleteAfterSuperEJBRemove(true); } catch (Exception ex) { processContainerException(ex); } } /** Called in a CMP supported environment. Notifies the container that * ejbSelect had been called. * * This is SunContainerHelper specific code. * * @see getContainer(Object) * @param container a Container instance for the request. */ public void preSelect(Object container) { ((Container)container).preSelect(); } /** Called in a CMP environment to lookup PersistenceManagerFactory * referenced by this Container instance as the CMP resource. * * This is SunContainerHelper specific code. * * @see getContainer(Object) * @param container a Container instance for the request. */ public PersistenceManagerFactory getPersistenceManagerFactory(Object container) { Object rc = null; PersistenceManagerFactoryImpl pmf = null; ResourceReferenceDescriptor cmpResource = ((Container)container).getEjbDescriptor(). getEjbBundleDescriptor().getCMPResourceReference(); String name = cmpResource.getJndiName(); try { InitialContext ic = new InitialContext(); rc = ic.lookup(name); if (rc instanceof PersistenceManagerFactoryImpl) { pmf = (PersistenceManagerFactoryImpl)rc; } else if (rc instanceof javax.sql.DataSource) { pmf = new PersistenceManagerFactoryImpl(); pmf.setConnectionFactoryName(ConnectorsUtil.getPMJndiName(name)); Iterator it = cmpResource.getProperties(); if (it != null) { while (it.hasNext()) { NameValuePairDescriptor prop = (NameValuePairDescriptor)it.next(); String n = prop.getName(); // Any value that is not "true" is treated as "false": boolean value = Boolean.valueOf(prop.getValue()).booleanValue(); pmf.setBooleanProperty(n, value); } } } else { RuntimeException e = new JDOFatalUserException(I18NHelper.getMessage( messages, "ejb.jndi.unexpectedinstance", //NOI18N name, rc.getClass().getName())); logger.severe(e.toString()); throw e; } } catch (javax.naming.NamingException ex) { RuntimeException e = new JDOFatalUserException(I18NHelper.getMessage( messages, "ejb.jndi.lookupfailed", name), ex); //NOI18N logger.severe(e.toString()); throw e; } return pmf; } /** * Called in CMP environment to get NumericConverter policy referenced * by this Container instance. * @see getContainer(Object) * @param container a Container instance for the request * @return a valid NumericConverter policy type */ public int getNumericConverterPolicy(Object container) { return NumericConverter.DEFAULT_POLICY; } /** Called in a unspecified transaction context of a managed environment. * According to p.364 of EJB 2.0 spec, CMP may need to manage * its own transaction when its transaction attribute is * NotSupported, Never, Supports. * This is a generic implementation. * Application server may like to overwrite this if necessary. * * @param pm PersistenceManager */ public void beginInternalTransaction(PersistenceManager pm) { pm.currentTransaction().begin(); } /** Called in a unspecified transaction context of a managed environment. * According to p.364 of EJB 2.0 spec, CMP may need to manage * its own transaction when its transaction attribute is * NotSupported, Never, Supports. * This is a generic implementation. * Application server may like to overwrite this if necessary. * * @param pm PersistenceManager */ public void commitInternalTransaction(PersistenceManager pm) { pm.currentTransaction().commit(); } /** Called in a unspecified transaction context of a managed environment. * According to p.364 of EJB 2.0 spec, CMP may need to manage * its own transaction when its transaction attribute is * NotSupported, Never, Supports. * This is a generic implementation. * Application server may like to overwrite this if necessary. * * @param pm PersistenceManager */ public void rollbackInternalTransaction(PersistenceManager pm) { pm.currentTransaction().rollback(); } /** Called from read-only beans to suspend current transaction. * This will guarantee that PersistenceManager is not bound to * any transaction. * * @return javax.transaction.Transaction object representing * the suspended transaction. * Returns null if the calling thread is not associated * with a transaction. */ public javax.transaction.Transaction suspendCurrentTransaction() { javax.transaction.Transaction tx = null; try { tx = getLocalTransactionManager().suspend(); } catch (Exception ex) { processContainerException(ex); } return tx; } /** Called from read-only beans to resume current transaction. * This will guarantee that the transaction continues to run after * read-only bean accessed its PersistenceManager. * * @param tx - The javax.transaction.Transaction object that * represents the transaction to be resumed. If this object had been * returned by #suspendCurrentTransaction() call it will be null in * case calling thread was not associated with a transaction. */ public void resumeCurrentTransaction(javax.transaction.Transaction tx) { try { // Resume only real (i.e. not null transaction) if (tx != null) { getLocalTransactionManager().resume(tx); } } catch (Exception ex) { processContainerException(ex); } } /** * Checks the caught Exception, and rethrows it if it is * of one of known types, or converts to an EJBException * otherwise. * * @param ex the Exception to process. * @throws RuntimeException of the appropriate type. */ private void processContainerException(Exception ex) { if (ex instanceof EJBException) { throw (EJBException)ex; } else if (ex instanceof IllegalArgumentException || ex instanceof IllegalStateException) { throw (RuntimeException)ex; } else if (ex instanceof JDOException) { throw (JDOException)ex; } else { throw new EJBException(ex); } } }