/** * EasyBeans * Copyright (C) 2008 Bull S.A.S. * Contact: easybeans@ow2.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * -------------------------------------------------------------------------- * $Id: ContainerJNDIResolver.java 5369 2010-02-24 14:58:19Z benoitf $ * -------------------------------------------------------------------------- */ package org.ow2.easybeans.resolver; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.ow2.easybeans.resolver.api.EZBApplicationJNDIResolver; import org.ow2.easybeans.resolver.api.EZBContainerJNDIResolver; import org.ow2.easybeans.resolver.api.EZBJNDIBeanData; import org.ow2.easybeans.resolver.api.EZBJNDIData; import org.ow2.util.archive.api.ArchiveException; import org.ow2.util.archive.api.IArchive; import org.ow2.util.log.Log; import org.ow2.util.log.LogFactory; /** * JNDI resolver for a container. It can answer to any request about beans of a given container. * @author Florent Benoit */ public class ContainerJNDIResolver extends CommonJNDIResolver implements EZBContainerJNDIResolver { /** * Logger. */ private static Log logger = LogFactory.getLog(ContainerJNDIResolver.class); /** * URL of this container resolver. */ private URL containerURL = null; /** * Link to an Application JNDI Resolver. */ private EZBApplicationJNDIResolver applicationJNDIResolver = null; /** * Map beween interface name and a map between bean name and the JNDI data. */ private Map<String, Map<String, EZBJNDIBeanData>> interfacesMap; /** * Map beween message destination name and the JNDI data. */ private Map<String, EZBJNDIData> messageDestinationMap; /** * Default constructor. * @param archive the archive of the given container. */ public ContainerJNDIResolver(final IArchive archive) { try { this.containerURL = archive.getURL(); } catch (ArchiveException e) { throw new IllegalArgumentException("Cannot get URL from archive '" + archive + "'."); } this.interfacesMap = new HashMap<String, Map<String, EZBJNDIBeanData>>(); this.messageDestinationMap = new HashMap<String, EZBJNDIData>(); } /** * @return URL used by this resolver. */ public URL getURL() { return this.containerURL; } /** * Allows to find EJB JNDI name. * @return a list of matching JNDI objects for the given interface and bean * name. * @param interfaceName the name of the interface that EJBs are * implementing. */ public List<EZBJNDIBeanData> getEJBJNDINames(final String interfaceName) { // Return a list with all the beans available for this interface return getEJBJNDINames(interfaceName, null); } /** * @return the application JNDI Resolver. */ public EZBApplicationJNDIResolver getApplicationJNDIResolver() { return this.applicationJNDIResolver; } /** * Sets the application resolver. * @param applicationJNDIResolver the application resolver */ public void setApplicationJNDIResolver(final EZBApplicationJNDIResolver applicationJNDIResolver) { this.applicationJNDIResolver = applicationJNDIResolver; } /** * Allows to find EJB JNDI name. * @return a list of matching JNDI objects for the given interface and bean * name. * @param interfaceName the name of the interface that EJBs are * implementing. * @param beanName the name of the bean on which we need to find JNDI name. */ public List<EZBJNDIBeanData> getEJBJNDINames(final String interfaceName, final String beanName) { // Ask also EAR if present return getEJBJNDINames(interfaceName, beanName, true); } /** * Allows to find EJB JNDI name. * @return a list of matching JNDI objects for the given interface and bean * name. * @param interfaceName the name of the interface that EJBs are * implementing. * @param beanName the name of the bean on which we need to find JNDI name. * @param askParent allow to disallow request to parent. */ public List<EZBJNDIBeanData> getEJBJNDINames(final String interfaceName, final String beanName, final boolean askParent) { // Get available beans for the given interface name Map<String, EZBJNDIBeanData> beansMap = this.interfacesMap.get(interfaceName); // No beans for the given interface if (beansMap == null) { // Not found, check in the other containers of the EAR (if any) return getEJBJNDINameInEAR(interfaceName, beanName, askParent); } // No bean name, use all values if (beanName == null || "".equals(beanName)) { Collection<EZBJNDIBeanData> beanValues = beansMap.values(); // Not found, check in the other containers of the EAR if (beanValues == null || beanValues.isEmpty()) { // Not found, check in the other containers of the EAR (if any) return getEJBJNDINameInEAR(interfaceName, beanName, askParent); } // Return a list with all the beans available for this interface return new ArrayList<EZBJNDIBeanData>(beanValues); } // Is that the bean name exists and there is an ejb-link in this name ? String newBeanname = beanName; if (beanName.indexOf("#") > 0) { // extract only the bean name newBeanname = beanName.split("#")[1]; logger.debug("EJB-LINK not fully supported for interface '" + interfaceName + "', and bean name '" + beanName + "' in container '" + this.containerURL + "'."); } // Build list for the return value List<EZBJNDIBeanData> beanDataList = new ArrayList<EZBJNDIBeanData>(); // Bean name is here, use it EZBJNDIBeanData beanData = beansMap.get(newBeanname); // Found a value, add it if (beanData == null) { // Not found, check in the other containers of the EAR (if any) return getEJBJNDINameInEAR(interfaceName, newBeanname, askParent); } // Add the local instance found beanDataList.add(beanData); // Return value return beanDataList; } /** * Allows to find EJB JNDI name in the EAR if the container is packaged * within an EAR. * @return a list of matching JNDI objects for the given interface and bean * name. * @param interfaceName the name of the interface that EJBs are * implementing. * @param beanName the name of the bean on which we need to find JNDI name. * @param enabled allow to disallow request to parent. */ protected List<EZBJNDIBeanData> getEJBJNDINameInEAR(final String interfaceName, final String beanName, final boolean enabled) { // If container is not inside an EAR or that recursion is turned off // stop here if (!enabled || this.applicationJNDIResolver == null) { return Collections.emptyList(); } // Ask the resolver of the EAR return this.applicationJNDIResolver.getEJBJNDINames(interfaceName, beanName); } /** * Adds a new JNDI name for the given interface name / bean name. * @param interfaceName the given interface * @param jndiData data for the JNDI Name entry */ public void addEJBJNDIName(final String interfaceName, final EZBJNDIBeanData jndiData) { // Get beans map Map<String, EZBJNDIBeanData> beansMap = this.interfacesMap.get(interfaceName); // Null ? create a new one if (beansMap == null) { beansMap = new HashMap<String, EZBJNDIBeanData>(); this.interfacesMap.put(interfaceName, beansMap); } String beanName = jndiData.getBeanName(); // Existing info about the bean ? EZBJNDIData existingData = beansMap.get(beanName); if (existingData != null) { logger.warn("Data already set for '" + jndiData + "' for the container URL '" + this.containerURL + "'."); } // Put info beansMap.put(beanName, jndiData); } /** * Adds a new JNDI name for the given message destination name. * @param messageDestinationName the given message destination name. * @param jndiData data for the JNDI Name entry */ public void addMessageDestinationJNDIName(final String messageDestinationName, final EZBJNDIData jndiData) { EZBJNDIData existingData = this.messageDestinationMap.get(messageDestinationName); if (existingData != null) { logger.warn("JNDI Name for Message destination name ''{0}'' was already set with value ''{1}}'", messageDestinationName, jndiData.getName()); } this.messageDestinationMap.put(messageDestinationName, jndiData); } /** * Allows to find Message Destination JNDI name. * @return a list of matching JNDI objects for the given message destination name. * @param messageDestinationName the name of the message destination. */ public List<EZBJNDIData> getMessageDestinationJNDINames(final String messageDestinationName) { // Ask EAR if not found return getMessageDestinationJNDINames(messageDestinationName, true); } /** * Allows to find Message Destination JNDI name. * @param messageDestinationName the name of the message destination. * @param askParent allow to disallow request to parent. * @return a list of matching JNDI objects for the given message destination name. */ public List<EZBJNDIData> getMessageDestinationJNDINames(final String messageDestinationName, final boolean askParent) { // Build list for the return value List<EZBJNDIData> dataList = new ArrayList<EZBJNDIData>(); // Name of a jar in the destination link ? String newMessageDestinationName = messageDestinationName; if (newMessageDestinationName.indexOf("#") > 0) { // extract only the destination name newMessageDestinationName = messageDestinationName.split("#")[1]; } // get metadata EZBJNDIData data = this.messageDestinationMap.get(newMessageDestinationName); // Found a value, add it if (data == null) { // Not found, check in the other containers of the EAR (if any) return getMessageDestinationJNDINameInEAR(newMessageDestinationName, askParent); } // Add the local instance found dataList.add(data); return dataList; } /** * Allows to find MessageDestination JNDI name in the EAR if the container is packaged * within an EAR. * @return a list of matching JNDI objects for the message destination name * @param messageDestinationName the name of the message destination * @param enabled allow to disallow request to parent. */ protected List<EZBJNDIData> getMessageDestinationJNDINameInEAR(final String messageDestinationName, final boolean enabled) { // If container is not inside an EAR or that recursion is turned off // stop here if (!enabled || this.applicationJNDIResolver == null) { return Collections.emptyList(); } // Ask the resolver of the EAR return this.applicationJNDIResolver.getMessageDestinationJNDINames(messageDestinationName); } }