1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.portal.service.spring;
35
36 import fr.paris.lutece.portal.service.init.LuteceInitException;
37 import fr.paris.lutece.portal.service.plugin.Plugin;
38 import fr.paris.lutece.portal.service.plugin.PluginEvent;
39 import fr.paris.lutece.portal.service.plugin.PluginEventListener;
40 import fr.paris.lutece.portal.service.plugin.PluginService;
41 import fr.paris.lutece.portal.service.util.AppLogService;
42 import fr.paris.lutece.portal.service.util.AppPathService;
43
44 import org.apache.commons.lang.StringUtils;
45
46 import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
47
48 import org.springframework.context.ApplicationContext;
49 import org.springframework.context.support.AbstractApplicationContext;
50
51 import org.springframework.web.context.support.GenericWebApplicationContext;
52
53 import java.io.File;
54 import java.io.FilenameFilter;
55
56 import java.util.ArrayList;
57 import java.util.Date;
58 import java.util.HashMap;
59 import java.util.List;
60 import java.util.Map;
61
62 import javax.servlet.ServletContext;
63
64
65
66
67
68
69
70 public final class SpringContextService implements PluginEventListener
71 {
72 private static final String PATH_CONF = "/WEB-INF/conf/";
73 private static final String DIR_PLUGINS = "plugins/";
74 private static final String DIR_OVERRIDE = "override/";
75 private static final String DIR_OVERRIDE_PLUGINS = DIR_OVERRIDE + DIR_PLUGINS;
76 private static final String SUFFIX_CONTEXT_FILE = "_context.xml";
77 private static final String FILE_CORE_CONTEXT = "core_context.xml";
78 private static ApplicationContext _context;
79 private static Map<Class, List> _mapBeansOfType = new HashMap<Class, List>( );
80 private static SpringContextService _instance = new SpringContextService( );
81
82
83 private SpringContextService( )
84 {
85 }
86
87
88
89
90
91
92
93
94
95
96
97 public static <T> T getBean( String strName )
98 {
99 return (T) _context.getBean( strName );
100 }
101
102
103
104
105
106
107
108
109
110 @Deprecated
111 public static Object getPluginBean( String strPluginName, String strName )
112 {
113 return _context.getBean( strName );
114 }
115
116
117
118
119
120
121
122
123
124
125 public static void init( ServletContext servletContext )
126 throws LuteceInitException
127 {
128 try
129 {
130
131 PluginService.registerPluginEventListener( _instance );
132
133
134 Date dateBegin = new Date( );
135
136
137 String strConfPath = AppPathService.getAbsolutePathFromRelativePath( PATH_CONF );
138 String strContextFile = "file:" + strConfPath + FILE_CORE_CONTEXT;
139
140 GenericWebApplicationContext gwac = new GenericWebApplicationContext( servletContext );
141 gwac.setId( getContextName( servletContext ) );
142
143 XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader( gwac );
144 xmlReader.loadBeanDefinitions( strContextFile );
145
146
147 AppLogService.info( "Context file loaded : " + FILE_CORE_CONTEXT );
148
149
150
151
152
153 String strConfPluginsPath = strConfPath + DIR_PLUGINS;
154 File dirConfPlugins = new File( strConfPluginsPath );
155 FilenameFilter filterContext = new ContextFileFilter( );
156 String[] filesContext = dirConfPlugins.list( filterContext );
157
158 loadContexts( filesContext, strConfPluginsPath, xmlReader );
159
160
161 AppLogService.info( "Loading plugins context overrides" );
162
163 String strCoreContextOverrideFile = strConfPath + DIR_OVERRIDE + FILE_CORE_CONTEXT;
164 File fileCoreContextOverride = new File( strCoreContextOverrideFile );
165
166 if ( fileCoreContextOverride.exists( ) )
167 {
168 AppLogService.debug( "Context file loaded : core_context" );
169 xmlReader.loadBeanDefinitions( "file:" + strCoreContextOverrideFile );
170 }
171 else
172 {
173 AppLogService.debug( "No core_context override found" );
174 }
175
176
177 String strConfPluginsOverridePath = strConfPath + DIR_OVERRIDE_PLUGINS;
178 File dirConfOverridePlugins = new File( strConfPluginsOverridePath );
179
180 if ( dirConfOverridePlugins.exists( ) )
181 {
182 String[] filesOverrideContext = dirConfOverridePlugins.list( filterContext );
183 loadContexts( filesOverrideContext, strConfPluginsOverridePath, xmlReader );
184 }
185
186 gwac.refresh( );
187
188 _context = gwac;
189
190 AppLogService.info( "Spring context loaded in " + ( new Date( ).getTime( ) - dateBegin.getTime( ) ) +
191 "ms" );
192 }
193 catch ( Exception e )
194 {
195 AppLogService.error( "Error initializing Spring Context Service " + e.getMessage( ), e );
196 throw new LuteceInitException( "Error initializing Spring Context Service", e );
197 }
198 }
199
200
201
202
203
204
205 private static String getContextName( ServletContext servletContext )
206 {
207 String name = "lutece";
208
209 if ( servletContext != null )
210 {
211 String contextName = servletContext.getServletContextName( );
212
213 if ( contextName == null )
214 {
215 contextName = servletContext.getContextPath( );
216 }
217
218 if ( StringUtils.isNotBlank( contextName ) )
219 {
220 name = contextName;
221 }
222 }
223
224 return name;
225 }
226
227
228
229
230
231
232
233 private static void loadContexts( String[] filesContext, String strConfPluginsPath,
234 XmlBeanDefinitionReader xmlReader )
235 {
236 for ( String fileContext : filesContext )
237 {
238 String[] file = { "file:" + strConfPluginsPath + fileContext };
239
240
241 try
242 {
243
244 xmlReader.loadBeanDefinitions( file );
245 AppLogService.info( "Context file loaded : " + fileContext );
246 }
247 catch ( Exception e )
248 {
249 AppLogService.error( "Unable to load Spring context file : " + fileContext + " - cause : " +
250 e.getMessage( ), e );
251 }
252 }
253 }
254
255
256
257
258
259
260 public static ApplicationContext getContext( )
261 {
262 return _context;
263 }
264
265
266
267
268
269
270
271 public static <T> List<T> getBeansOfType( Class<T> classDef )
272 {
273
274 List<T> list = _mapBeansOfType.get( classDef );
275
276 if ( list != null )
277 {
278 return new ArrayList<T>( list );
279 }
280
281
282 list = new ArrayList<T>( );
283
284 Map<String, T> map = _context.getBeansOfType( classDef );
285 String[] sBeanNames = map.keySet( ).toArray( new String[map.size( )] );
286
287 for ( String strBeanName : sBeanNames )
288 {
289 String strPluginPrefix = getPrefix( strBeanName );
290
291 if ( ( strPluginPrefix == null ) || ( isEnabled( strPluginPrefix ) ) )
292 {
293 list.add( map.get( strBeanName ) );
294 }
295 }
296
297 _mapBeansOfType.put( classDef, new ArrayList<T>( list ) );
298
299 return list;
300 }
301
302
303
304
305
306
307 private static String getPrefix( String strBeanName )
308 {
309 int nPos = strBeanName.indexOf( "." );
310
311 if ( nPos > 0 )
312 {
313 return strBeanName.substring( 0, nPos );
314 }
315
316 return null;
317 }
318
319
320
321
322
323
324 private static boolean isEnabled( String strPrefix )
325 {
326 Plugin plugin = PluginService.getPlugin( strPrefix );
327
328 if ( ( plugin != null ) && plugin.isInstalled( ) )
329 {
330 return true;
331 }
332
333 return false;
334 }
335
336
337
338
339 @Override
340 public void processPluginEvent( PluginEvent event )
341 {
342
343 if ( ( event.getEventType( ) == PluginEvent.PLUGIN_INSTALLED ) ||
344 ( event.getEventType( ) == PluginEvent.PLUGIN_UNINSTALLED ) )
345 {
346 if ( !_mapBeansOfType.isEmpty( ) )
347 {
348 _mapBeansOfType.clear( );
349 AppLogService.info( "SpringService cache cleared due to a plugin installation change - Plugin : " +
350 event.getPlugin( ).getName( ) );
351 }
352 }
353 }
354
355
356
357
358
359 public static void shutdown( )
360 {
361 if ( _context != null )
362 {
363 ( (AbstractApplicationContext) _context ).close( );
364 }
365 }
366
367
368
369
370 static class ContextFileFilter implements FilenameFilter
371 {
372
373
374
375
376
377
378 @Override
379 public boolean accept( File file, String strName )
380 {
381 return strName.endsWith( SUFFIX_CONTEXT_FILE );
382 }
383 }
384 }