001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.context.access; 018 019import javax.naming.NamingException; 020 021import org.springframework.beans.BeansException; 022import org.springframework.beans.factory.access.BeanFactoryLocator; 023import org.springframework.beans.factory.access.BeanFactoryReference; 024import org.springframework.beans.factory.access.BootstrapException; 025import org.springframework.context.ApplicationContext; 026import org.springframework.context.support.ClassPathXmlApplicationContext; 027import org.springframework.jndi.JndiLocatorSupport; 028import org.springframework.util.StringUtils; 029 030/** 031 * BeanFactoryLocator implementation that creates the BeanFactory from one or 032 * more classpath locations specified in a JNDI environment variable. 033 * 034 * <p>This default implementation creates a 035 * {@link org.springframework.context.support.ClassPathXmlApplicationContext}. 036 * Subclasses may override {@link #createBeanFactory} for custom instantiation. 037 * 038 * @author Colin Sampaleanu 039 * @author Juergen Hoeller 040 * @see #createBeanFactory 041 */ 042public class ContextJndiBeanFactoryLocator extends JndiLocatorSupport implements BeanFactoryLocator { 043 044 /** 045 * Any number of these characters are considered delimiters between 046 * multiple bean factory config paths in a single String value. 047 */ 048 public static final String BEAN_FACTORY_PATH_DELIMITERS = ",; \t\n"; 049 050 051 /** 052 * Load/use a bean factory, as specified by a factory key which is a JNDI 053 * address, of the form {@code java:comp/env/ejb/BeanFactoryPath}. The 054 * contents of this JNDI location must be a string containing one or more 055 * classpath resource names (separated by any of the delimiters '{@code ,; \t\n}' 056 * if there is more than one. The resulting BeanFactory (or ApplicationContext) 057 * will be created from the combined resources. 058 * @see #createBeanFactory 059 */ 060 @Override 061 public BeanFactoryReference useBeanFactory(String factoryKey) throws BeansException { 062 try { 063 String beanFactoryPath = lookup(factoryKey, String.class); 064 if (logger.isTraceEnabled()) { 065 logger.trace("Bean factory path from JNDI environment variable [" + factoryKey + 066 "] is: " + beanFactoryPath); 067 } 068 String[] paths = StringUtils.tokenizeToStringArray(beanFactoryPath, BEAN_FACTORY_PATH_DELIMITERS); 069 return createBeanFactory(paths); 070 } 071 catch (NamingException ex) { 072 throw new BootstrapException("Define an environment variable [" + factoryKey + "] containing " + 073 "the class path locations of XML bean definition files", ex); 074 } 075 } 076 077 /** 078 * Create the BeanFactory instance, given an array of class path resource Strings 079 * which should be combined. This is split out as a separate method so that 080 * subclasses can override the actual BeanFactory implementation class. 081 * <p>Delegates to {@code createApplicationContext} by default, 082 * wrapping the result in a ContextBeanFactoryReference. 083 * @param resources an array of Strings representing classpath resource names 084 * @return the created BeanFactory, wrapped in a BeanFactoryReference 085 * (for example, a ContextBeanFactoryReference wrapping an ApplicationContext) 086 * @throws BeansException if factory creation failed 087 * @see #createApplicationContext 088 * @see ContextBeanFactoryReference 089 */ 090 protected BeanFactoryReference createBeanFactory(String[] resources) throws BeansException { 091 ApplicationContext ctx = createApplicationContext(resources); 092 return new ContextBeanFactoryReference(ctx); 093 } 094 095 /** 096 * Create the ApplicationContext instance, given an array of class path resource 097 * Strings which should be combined 098 * @param resources an array of Strings representing classpath resource names 099 * @return the created ApplicationContext 100 * @throws BeansException if context creation failed 101 */ 102 protected ApplicationContext createApplicationContext(String[] resources) throws BeansException { 103 return new ClassPathXmlApplicationContext(resources); 104 } 105 106}