001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.geoserver.platform;
006:
007: import org.geotools.util.SoftValueHashMap;
008: import org.springframework.beans.BeansException;
009: import org.springframework.context.ApplicationContext;
010: import org.springframework.context.ApplicationContextAware;
011: import org.springframework.context.ApplicationEvent;
012: import org.springframework.context.ApplicationListener;
013: import org.springframework.context.event.ContextRefreshedEvent;
014:
015: import java.util.ArrayList;
016: import java.util.List;
017:
018: /**
019: * Utility class uses to process GeoServer extension points.
020: * <p>
021: * An instance of this class needs to be registered in spring context as follows.
022: * <code>
023: * <pre>
024: * <bean id="geoserverExtensions" class="org.geoserver.GeoServerExtensions"/>
025: * </pre>
026: * </code>
027: * It must be a singleton, and must not be loaded lazily. Furthermore, this
028: * bean must be loaded before any beans that use it.
029: * </p>
030: * @author Justin Deoliveira, The Open Planning Project
031: * @author Andrea Aime, The Open Planning Project
032: *
033: */
034: public class GeoServerExtensions implements ApplicationContextAware,
035: ApplicationListener {
036:
037: /**
038: * Caches the names of the beans for a particular type, so that the lookup (expensive)
039: * wont' be needed. We cache names instead of beans because doing the latter we would
040: * break the "singleton=false" directive of some beans
041: */
042: static SoftValueHashMap extensionsCache = new SoftValueHashMap(40);
043:
044: /**
045: * A static application context
046: */
047: static ApplicationContext context;
048:
049: /**
050: * Sets the web application context to be used for looking up extensions.
051: * <p>
052: * This method is called by the spring container, and should never be called
053: * by client code. If client needs to supply a particular context, methods
054: * which take a context are available.
055: * </p>
056: * <p>
057: * This is the context that is used for methods which dont supply their
058: * own context.
059: * </p>
060: */
061: public void setApplicationContext(ApplicationContext context)
062: throws BeansException {
063: GeoServerExtensions.context = context;
064: extensionsCache.clear();
065: }
066:
067: /**
068: * Loads all extensions implementing or extending <code>extensionPoint</code>.
069: *
070: * @param extensionPoint The class or interface of the extensions.
071: * @param context The context in which to perform the lookup.
072: *
073: * @return A collection of the extensions, or an empty collection.
074: */
075: public static final List extensions(Class extensionPoint,
076: ApplicationContext context) {
077: String[] names = (String[]) extensionsCache.get(extensionPoint);
078: if (names == null) {
079: names = context.getBeanNamesForType(extensionPoint);
080: extensionsCache.put(extensionPoint, names);
081: }
082: List result = new ArrayList(names.length);
083: for (int i = 0; i < names.length; i++) {
084: result.add(context.getBean(names[i]));
085: }
086: return result;
087: }
088:
089: /**
090: * Loads all extensions implementing or extending <code>extensionPoint</code>.
091: * <p>
092: * This method uses the "default" application context to perform the lookup.
093: * See {@link #setApplicationContext(ApplicationContext)}.
094: * </p>
095: * @param extensionPoint The class or interface of the extensions.
096: *
097: * @return A collection of the extensions, or an empty collection.
098: */
099: public static final List extensions(Class extensionPoint) {
100: return extensions(extensionPoint, context);
101: }
102:
103: /**
104: * Returns a specific bean given its name
105: * @param name
106: * @return
107: */
108: public static final Object bean(String name) {
109: return context.getBean(name);
110: }
111:
112: public void onApplicationEvent(ApplicationEvent event) {
113: if (event instanceof ContextRefreshedEvent)
114: extensionsCache.clear();
115: }
116: }
|