001/* 002 * Copyright 2002-2014 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.support; 018 019import org.springframework.beans.factory.BeanNameAware; 020import org.springframework.beans.factory.InitializingBean; 021import org.springframework.context.ApplicationContext; 022import org.springframework.util.Assert; 023import org.springframework.util.StringUtils; 024 025/** 026 * {@link AbstractRefreshableApplicationContext} subclass that adds common handling 027 * of specified config locations. Serves as base class for XML-based application 028 * context implementations such as {@link ClassPathXmlApplicationContext} and 029 * {@link FileSystemXmlApplicationContext}, as well as 030 * {@link org.springframework.web.context.support.XmlWebApplicationContext} and 031 * {@link org.springframework.web.portlet.context.XmlPortletApplicationContext}. 032 * 033 * @author Juergen Hoeller 034 * @since 2.5.2 035 * @see #setConfigLocation 036 * @see #setConfigLocations 037 * @see #getDefaultConfigLocations 038 */ 039public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext 040 implements BeanNameAware, InitializingBean { 041 042 private String[] configLocations; 043 044 private boolean setIdCalled = false; 045 046 047 /** 048 * Create a new AbstractRefreshableConfigApplicationContext with no parent. 049 */ 050 public AbstractRefreshableConfigApplicationContext() { 051 } 052 053 /** 054 * Create a new AbstractRefreshableConfigApplicationContext with the given parent context. 055 * @param parent the parent context 056 */ 057 public AbstractRefreshableConfigApplicationContext(ApplicationContext parent) { 058 super(parent); 059 } 060 061 062 /** 063 * Set the config locations for this application context in init-param style, 064 * i.e. with distinct locations separated by commas, semicolons or whitespace. 065 * <p>If not set, the implementation may use a default as appropriate. 066 */ 067 public void setConfigLocation(String location) { 068 setConfigLocations(StringUtils.tokenizeToStringArray(location, CONFIG_LOCATION_DELIMITERS)); 069 } 070 071 /** 072 * Set the config locations for this application context. 073 * <p>If not set, the implementation may use a default as appropriate. 074 */ 075 public void setConfigLocations(String... locations) { 076 if (locations != null) { 077 Assert.noNullElements(locations, "Config locations must not be null"); 078 this.configLocations = new String[locations.length]; 079 for (int i = 0; i < locations.length; i++) { 080 this.configLocations[i] = resolvePath(locations[i]).trim(); 081 } 082 } 083 else { 084 this.configLocations = null; 085 } 086 } 087 088 /** 089 * Return an array of resource locations, referring to the XML bean definition 090 * files that this context should be built with. Can also include location 091 * patterns, which will get resolved via a ResourcePatternResolver. 092 * <p>The default implementation returns {@code null}. Subclasses can override 093 * this to provide a set of resource locations to load bean definitions from. 094 * @return an array of resource locations, or {@code null} if none 095 * @see #getResources 096 * @see #getResourcePatternResolver 097 */ 098 protected String[] getConfigLocations() { 099 return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations()); 100 } 101 102 /** 103 * Return the default config locations to use, for the case where no 104 * explicit config locations have been specified. 105 * <p>The default implementation returns {@code null}, 106 * requiring explicit config locations. 107 * @return an array of default config locations, if any 108 * @see #setConfigLocations 109 */ 110 protected String[] getDefaultConfigLocations() { 111 return null; 112 } 113 114 /** 115 * Resolve the given path, replacing placeholders with corresponding 116 * environment property values if necessary. Applied to config locations. 117 * @param path the original file path 118 * @return the resolved file path 119 * @see org.springframework.core.env.Environment#resolveRequiredPlaceholders(String) 120 */ 121 protected String resolvePath(String path) { 122 return getEnvironment().resolveRequiredPlaceholders(path); 123 } 124 125 126 @Override 127 public void setId(String id) { 128 super.setId(id); 129 this.setIdCalled = true; 130 } 131 132 /** 133 * Sets the id of this context to the bean name by default, 134 * for cases where the context instance is itself defined as a bean. 135 */ 136 @Override 137 public void setBeanName(String name) { 138 if (!this.setIdCalled) { 139 super.setId(name); 140 setDisplayName("ApplicationContext '" + name + "'"); 141 } 142 } 143 144 /** 145 * Triggers {@link #refresh()} if not refreshed in the concrete context's 146 * constructor already. 147 */ 148 @Override 149 public void afterPropertiesSet() { 150 if (!isActive()) { 151 refresh(); 152 } 153 } 154 155}