001package fr.ifremer.adagio.core.service; 002 003/* 004 * #%L 005 * SIH-Adagio Core Shared 006 * $Id: ServiceLocator.java 12053 2014-04-22 09:34:15Z tc1fbb1 $ 007 * $HeadURL: https://forge.ifremer.fr/svn/sih-adagio/tags/adagio-3.5.6/core-shared/src/main/java/fr/ifremer/adagio/core/service/ServiceLocator.java $ 008 * %% 009 * Copyright (C) 2012 - 2013 Ifremer 010 * %% 011 * This program is free software: you can redistribute it and/or modify 012 * it under the terms of the GNU Affero General Public License as published by 013 * the Free Software Foundation, either version 3 of the License, or 014 * (at your option) any later version. 015 * 016 * This program is distributed in the hope that it will be useful, 017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 019 * GNU General Public License for more details. 020 * 021 * You should have received a copy of the GNU Affero General Public License 022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 023 * #L% 024 */ 025 026import java.io.Closeable; 027import java.io.IOException; 028 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.springframework.beans.factory.access.BeanFactoryLocator; 032import org.springframework.beans.factory.access.BeanFactoryReference; 033import org.springframework.context.ApplicationContext; 034import org.springframework.context.access.ContextSingletonBeanFactoryLocator; 035import org.springframework.context.support.AbstractApplicationContext; 036 037import fr.ifremer.adagio.core.service.referential.location.LocationService; 038import fr.ifremer.adagio.core.service.technical.CacheService; 039 040/** 041 * Locates and provides all available application services. 042 */ 043public class ServiceLocator implements Closeable { 044 045 /* Logger */ 046 private static final Log log = LogFactory.getLog(ServiceLocator.class); 047 048 /** 049 * The default bean reference factory location. 050 */ 051 private static final String DEFAULT_BEAN_REFERENCE_LOCATION = "beanRefFactory.xml"; 052 053 /** 054 * The default bean reference factory ID. 055 */ 056 private static final String DEFAULT_BEAN_REFERENCE_ID = "beanRefFactory"; 057 058 /** 059 * The shared instance of this ServiceLocator. 060 */ 061 private static ServiceLocator instance = new ServiceLocator(); 062 063 /** 064 * Indicates if the spring context is open or not. 065 */ 066 private boolean open = false; 067 068 protected ServiceLocator() { 069 // shouldn't be instantiated 070 init(null, null); 071 } 072 073 protected ServiceLocator(String beanFactoryReferenceLocation, 074 String beanRefFactoryReferenceId) { 075 init(beanFactoryReferenceLocation, beanRefFactoryReferenceId); 076 } 077 078 /** 079 * replace the default shared instance of this Class 080 * 081 * @param newInstance the new shared service locator instance. 082 */ 083 public static void setInstance(ServiceLocator newInstance) { 084 instance = newInstance; 085 } 086 087 /** 088 * Gets the shared instance of this Class 089 * 090 * @return the shared service locator instance. 091 */ 092 public static ServiceLocator instance() { 093 return instance; 094 } 095 096 /** 097 * The bean factory reference instance. 098 */ 099 private BeanFactoryReference beanFactoryReference; 100 101 /** 102 * The bean factory reference location. 103 */ 104 private String beanFactoryReferenceLocation; 105 106 /** 107 * The bean factory reference id. 108 */ 109 private String beanRefFactoryReferenceId; 110 111 /** 112 * Initializes the Spring application context from the given <code>beanFactoryReferenceLocation</code>. If <code>null</code> is 113 * specified for the <code>beanFactoryReferenceLocation</code> then the 114 * default application context will be used. 115 * 116 * @param beanFactoryReferenceLocation the location of the beanRefFactory reference. 117 */ 118 public synchronized void init(String beanFactoryReferenceLocation, 119 String beanRefFactoryReferenceId) { 120 // Log if default values are overrided 121 if (log.isDebugEnabled() && beanFactoryReferenceLocation != null && beanRefFactoryReferenceId != null) { 122 log.debug(String.format("Initializing ServiceLocator to use Spring bean factory [%s] at: %s", beanRefFactoryReferenceId, 123 beanFactoryReferenceLocation)); 124 } 125 126 this.beanFactoryReferenceLocation = 127 beanFactoryReferenceLocation == null ? 128 DEFAULT_BEAN_REFERENCE_LOCATION : 129 beanFactoryReferenceLocation; 130 this.beanRefFactoryReferenceId = beanRefFactoryReferenceId == null ? 131 DEFAULT_BEAN_REFERENCE_ID : 132 beanRefFactoryReferenceId; 133 this.beanFactoryReference = null; 134 } 135 136 /** 137 * Initializes the Spring application context from the given <code>beanFactoryReferenceLocation</code>. If <code>null</code> is 138 * specified for the <code>beanFactoryReferenceLocation</code> then the 139 * default application context will be used. 140 * 141 * @param beanFactoryReferenceLocation the location of the beanRefFactory reference. 142 */ 143 public synchronized void init(String beanFactoryReferenceLocation) { 144 this.beanFactoryReferenceLocation = beanFactoryReferenceLocation == null ? 145 DEFAULT_BEAN_REFERENCE_LOCATION : 146 beanFactoryReferenceLocation; 147 this.beanFactoryReference = null; 148 } 149 150 /** 151 * Shuts down the ServiceLocator and releases any used resources. 152 */ 153 public synchronized void shutdown() { 154 // Do not try to close if not already opened 155 if (!open) { 156 return; 157 } 158 if (log.isDebugEnabled()) { 159 log.debug("Close Spring application context"); 160 } 161 162 ((AbstractApplicationContext) getContext()).close(); 163 if (beanFactoryReference != null) { 164 beanFactoryReference.release(); 165 beanFactoryReference = null; 166 } 167 open = false; 168 } 169 170 /** 171 * Get a service. 172 * 173 * @param name name of the service (i.e name of the srping bean) 174 * @param serviceType type of service 175 * @param <S> type of the service 176 * @return the instanciated service 177 */ 178 public <S> S getService(String name, Class<S> serviceType) { 179 return getContext().getBean(name, serviceType); 180 } 181 182 /** 183 * Gets an instance of {@link LocationService}. 184 */ 185 public final LocationService getLocationService() { 186 return getService("locationService", LocationService.class); 187 } 188 189 190 /** 191 * Gets an instance of {@link CacheService}. 192 */ 193 public final CacheService getCacheService() { 194 return getService("cacheService", CacheService.class); 195 } 196 197 /** 198 * @return {@code true} if spring context is open, {@code false} otherwise. 199 * @since 3.5.2 200 */ 201 public boolean isOpen() { 202 return open; 203 } 204 205 /** 206 * Gets the Spring ApplicationContext. 207 */ 208 protected synchronized ApplicationContext getContext() { 209 if (beanFactoryReference == null) { 210 if (log.isDebugEnabled() && beanFactoryReferenceLocation != null && beanRefFactoryReferenceId != null) { 211 log.debug(String.format("Starting Spring application context using bean factory [%s] from file: %s", beanRefFactoryReferenceId, 212 beanFactoryReferenceLocation)); 213 } 214 BeanFactoryLocator beanFactoryLocator = 215 ContextSingletonBeanFactoryLocator.getInstance( 216 beanFactoryReferenceLocation); 217 beanFactoryReference = beanFactoryLocator 218 .useBeanFactory(beanRefFactoryReferenceId); 219 220 open = true; 221 } 222 return (ApplicationContext) beanFactoryReference.getFactory(); 223 } 224 225 @Override 226 public void close() throws IOException { 227 shutdown(); 228 } 229}