Source Code Cross Referenced for DiscoverSingleton.java in  » Library » Apache-common-Discovery » org » apache » commons » discovery » tools » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache common Discovery » org.apache.commons.discovery.tools 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.commons.discovery.tools;
018:
019:        import java.util.HashMap;
020:        import java.util.Properties;
021:
022:        import org.apache.commons.discovery.DiscoveryException;
023:        import org.apache.commons.discovery.jdk.JDKHooks;
024:        import org.apache.commons.discovery.resource.ClassLoaders;
025:
026:        /**
027:         * <p>Discover singleton service providers.
028:         * This 
029:         * </p>
030:         * 
031:         * <p>DiscoverSingleton instances are cached by the Discovery service,
032:         * keyed by a combination of
033:         * <ul>
034:         *   <li>thread context class loader,</li>
035:         *   <li>groupContext, and</li>
036:         *   <li>SPI.</li>
037:         * </ul>
038:         * This DOES allow multiple instances of a given <i>singleton</i> class
039:         * to exist for different class loaders and different group contexts.
040:         * </p>
041:         * 
042:         * <p>In the context of this package, a service interface is defined by a
043:         * Service Provider Interface (SPI).  The SPI is expressed as a Java interface,
044:         * abstract class, or (base) class that defines an expected programming
045:         * interface.
046:         * </p>
047:         * 
048:         * <p>DiscoverSingleton provides the <code>find</code> methods for locating and
049:         * instantiating a singleton instance of an implementation of a service (SPI).
050:         * Each form of <code>find</code> varies slightly, but they all perform the
051:         * same basic function.
052:         * 
053:         * The simplest <code>find</code> methods are intended for direct use by
054:         * components looking for a service.  If you are not sure which finder(s)
055:         * to use, you can narrow your search to one of these:
056:         * <ul>
057:         * <li>static Object find(Class spi);</li>
058:         * <li>static Object find(Class spi, Properties properties);</li>
059:         * <li>static Object find(Class spi, String defaultImpl);</li>
060:         * <li>static Object find(Class spi,
061:         *                        Properties properties, String defaultImpl);</li>
062:         * <li>static Object find(Class spi,
063:         *                        String propertiesFileName, String defaultImpl);</li>
064:         * <li>static Object find(String groupContext, Class spi,
065:         *                        Properties properties, String defaultImpl);</li>
066:         * <li>static Object find(String groupContext, Class spi,
067:         *                        String propertiesFileName, String defaultImpl);</li>
068:         * </ul>
069:         * 
070:         * The <code>DiscoverSingleton.find</code> methods proceed as follows:
071:         * </p>
072:         * <ul>
073:         *   <p><li>
074:         *   Examine an internal cache to determine if the desired service was
075:         *   previously identified and instantiated.  If found in cache, return it.
076:         *   </li></p>
077:         *   <p><li>
078:         *   Get the name of an implementation class.  The name is the first
079:         *   non-null value obtained from the following resources:
080:         *   <ul>
081:         *     <li>
082:         *     The value of the (scoped) system property whose name is the same as
083:         *     the SPI's fully qualified class name (as given by SPI.class.getName()).
084:         *     The <code>ScopedProperties</code> class provides a way to bind
085:         *     properties by classloader, in a secure hierarchy similar in concept
086:         *     to the way classloader find class and resource files.
087:         *     See <code>ScopedProperties</code> for more details.
088:         *     <p>If the ScopedProperties are not set by users, then behaviour
089:         *     is equivalent to <code>System.getProperty()</code>.
090:         *     </p>
091:         *     </li>
092:         *     <p><li>
093:         *     The value of a <code>Properties properties</code> property, if provided
094:         *     as a parameter, whose name is the same as the SPI's fully qualifed class
095:         *     name (as given by SPI.class.getName()).
096:         *     </li></p>
097:         *     <p><li>
098:         *     The value obtained using the JDK1.3+ 'Service Provider' specification
099:         *     (http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html) to locate a
100:         *     service named <code>SPI.class.getName()</code>.  This is implemented
101:         *     internally, so there is not a dependency on JDK 1.3+.
102:         *     </li></p>
103:         *   </ul>
104:         *   </li></p>
105:         *   <p><li>
106:         *   If the name of the implementation class is non-null, load that class.
107:         *   The class loaded is the first class loaded by the following sequence
108:         *   of class loaders:
109:         *   <ul>
110:         *     <li>Thread Context Class Loader</li>
111:         *     <li>DiscoverSingleton's Caller's Class Loader</li>
112:         *     <li>SPI's Class Loader</li>
113:         *     <li>DiscoverSingleton's (this class or wrapper) Class Loader</li>
114:         *     <li>System Class Loader</li>
115:         *   </ul>
116:         *   An exception is thrown if the class cannot be loaded.
117:         *   </li></p>
118:         *   <p><li>
119:         *   If the name of the implementation class is null, AND the default
120:         *   implementation class (<code>defaultImpl</code>) is null,
121:         *   then an exception is thrown.
122:         *   </li></p>
123:         *   <p><li>
124:         *   If the name of the implementation class is null, AND the default
125:         *   implementation class (<code>defaultImpl</code>) is non-null,
126:         *   then load the default implementation class.  The class loaded is the
127:         *   first class loaded by the following sequence of class loaders:
128:         *   <ul>
129:         *     <li>SPI's Class Loader</li>
130:         *     <li>DiscoverSingleton's (this class or wrapper) Class Loader</li>
131:         *     <li>System Class Loader</li>
132:         *   </ul>
133:         *   <p>
134:         *   This limits the scope in which the default class loader can be found
135:         *   to the SPI, DiscoverSingleton, and System class loaders.  The assumption
136:         *   here is that the default implementation is closely associated with the SPI
137:         *   or system, and is not defined in the user's application space.
138:         *   </p>
139:         *   <p>
140:         *   An exception is thrown if the class cannot be loaded.
141:         *   </p>
142:         *   </li></p>
143:         *   <p><li>
144:         *   Verify that the loaded class implements the SPI: an exception is thrown
145:         *   if the loaded class does not implement the SPI.
146:         *   </li></p>
147:         *   <p><li>
148:         *   Create an instance of the class.
149:         *   </li></p>
150:         * </ul>
151:         * 
152:         * <p>
153:         * Variances for various forms of the <code>find</code>
154:         * methods are discussed with each such method.
155:         * Variances include the following concepts:
156:         * <ul>
157:         *   <li><b>rootFinderClass</b> - a wrapper encapsulating a finder method
158:         *   (factory or other helper class).  The root finder class is used to
159:         *   determine the 'real' caller, and hence the caller's class loader -
160:         *   thereby preserving knowledge that is relevant to finding the
161:         *   correct/expected implementation class.
162:         *   </li>
163:         *   <li><b>propertiesFileName</b> - <code>Properties</code> may be specified
164:         *   directly, or by property file name.  A property file is loaded using the
165:         *   same sequence of class loaders used to load the SPI implementation:
166:         *   <ul>
167:         *     <li>Thread Context Class Loader</li>
168:         *     <li>DiscoverSingleton's Caller's Class Loader</li>
169:         *     <li>SPI's Class Loader</li>
170:         *     <li>DiscoverSingleton's (this class) Class Loader</li>
171:         *     <li>System Class Loader</li>
172:         *   </ul>
173:         *   </li>
174:         *   <li><b>groupContext</b> - differentiates service providers for different
175:         *   logical groups of service users, that might otherwise be forced to share
176:         *   a common service and, more importantly, a common configuration of that
177:         *   service.
178:         *   <p>The groupContext is used to qualify the name of the property file
179:         *   name: <code>groupContext + '.' + propertiesFileName</code>.  If that
180:         *   file is not found, then the unqualified propertyFileName is used.
181:         *   </p>
182:         *   <p>In addition, groupContext is used to qualify the name of the system
183:         *   property used to find the service implementation by prepending the value
184:         *   of <code>groupContext</code> to the property name:
185:         *   <code>groupContext&gt; + '.' + SPI.class.getName()</code>.
186:         *   Again, if a system property cannot be found by that name, then the
187:         *   unqualified property name is used.
188:         *   </p>
189:         *   </li>
190:         * </ul>
191:         * </p>
192:         * 
193:         * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation is modelled
194:         * after the SAXParserFactory and DocumentBuilderFactory implementations
195:         * (corresponding to the JAXP pluggability APIs) found in Apache Xerces.
196:         * </p>
197:         * 
198:         * @author Richard A. Sitze
199:         * @author Craig R. McClanahan
200:         * @author Costin Manolache
201:         * @version $Revision: 480374 $ $Date: 2006-11-28 19:33:25 -0800 (Tue, 28 Nov 2006) $
202:         */
203:        public class DiscoverSingleton {
204:            /********************** (RELATIVELY) SIMPLE FINDERS **********************
205:             * 
206:             * These finders are suitable for direct use in components looking for a
207:             * service.  If you are not sure which finder(s) to use, you can narrow
208:             * your search to one of these.
209:             */
210:
211:            /**
212:             * Find implementation of SPI.
213:             * 
214:             * @param spiClass Service Provider Interface Class.
215:             * 
216:             * @return Instance of a class implementing the SPI.
217:             * 
218:             * @exception DiscoveryException Thrown if the name of a class implementing
219:             *            the SPI cannot be found, if the class cannot be loaded and
220:             *            instantiated, or if the resulting class does not implement
221:             *            (or extend) the SPI.
222:             */
223:            public static Object find(Class spiClass) throws DiscoveryException {
224:                return find(null, new SPInterface(spiClass),
225:                        DiscoverClass.nullProperties,
226:                        DiscoverClass.nullDefaultImpl);
227:            }
228:
229:            /**
230:             * Find implementation of SPI.
231:             * 
232:             * @param spiClass Service Provider Interface Class.
233:             * 
234:             * @param properties Used to determine name of SPI implementation,
235:             *                   and passed to implementation.init() method if
236:             *                   implementation implements Service interface.
237:             * 
238:             * @return Instance of a class implementing the SPI.
239:             * 
240:             * @exception DiscoveryException Thrown if the name of a class implementing
241:             *            the SPI cannot be found, if the class cannot be loaded and
242:             *            instantiated, or if the resulting class does not implement
243:             *            (or extend) the SPI.
244:             */
245:            public static Object find(Class spiClass, Properties properties)
246:                    throws DiscoveryException {
247:                return find(null, new SPInterface(spiClass),
248:                        new PropertiesHolder(properties),
249:                        DiscoverClass.nullDefaultImpl);
250:            }
251:
252:            /**
253:             * Find implementation of SPI.
254:             * 
255:             * @param spiClass Service Provider Interface Class.
256:             * 
257:             * @param defaultImpl Default implementation.
258:             * 
259:             * @return Instance of a class implementing the SPI.
260:             * 
261:             * @exception DiscoveryException Thrown if the name of a class implementing
262:             *            the SPI cannot be found, if the class cannot be loaded and
263:             *            instantiated, or if the resulting class does not implement
264:             *            (or extend) the SPI.
265:             */
266:            public static Object find(Class spiClass, String defaultImpl)
267:                    throws DiscoveryException {
268:                return find(null, new SPInterface(spiClass),
269:                        DiscoverClass.nullProperties, new DefaultClassHolder(
270:                                defaultImpl));
271:            }
272:
273:            /**
274:             * Find implementation of SPI.
275:             * 
276:             * @param spiClass Service Provider Interface Class.
277:             * 
278:             * @param properties Used to determine name of SPI implementation,
279:             *                   and passed to implementation.init() method if
280:             *                   implementation implements Service interface.
281:             * 
282:             * @param defaultImpl Default implementation.
283:             * 
284:             * @return Instance of a class implementing the SPI.
285:             * 
286:             * @exception DiscoveryException Thrown if the name of a class implementing
287:             *            the SPI cannot be found, if the class cannot be loaded and
288:             *            instantiated, or if the resulting class does not implement
289:             *            (or extend) the SPI.
290:             */
291:            public static Object find(Class spiClass, Properties properties,
292:                    String defaultImpl) throws DiscoveryException {
293:                return find(null, new SPInterface(spiClass),
294:                        new PropertiesHolder(properties),
295:                        new DefaultClassHolder(defaultImpl));
296:            }
297:
298:            /**
299:             * Find implementation of SPI.
300:             * 
301:             * @param spiClass Service Provider Interface Class.
302:             * 
303:             * @param propertiesFileName Used to determine name of SPI implementation,
304:             *                   and passed to implementation.init() method if
305:             *                   implementation implements Service interface.
306:             * 
307:             * @param defaultImpl Default implementation.
308:             * 
309:             * @return Instance of a class implementing the SPI.
310:             * 
311:             * @exception DiscoveryException Thrown if the name of a class implementing
312:             *            the SPI cannot be found, if the class cannot be loaded and
313:             *            instantiated, or if the resulting class does not implement
314:             *            (or extend) the SPI.
315:             */
316:            public static Object find(Class spiClass,
317:                    String propertiesFileName, String defaultImpl)
318:                    throws DiscoveryException {
319:                return find(null, new SPInterface(spiClass),
320:                        new PropertiesHolder(propertiesFileName),
321:                        new DefaultClassHolder(defaultImpl));
322:            }
323:
324:            /*************** FINDERS FOR USE IN FACTORY/HELPER METHODS ***************
325:             */
326:
327:            /**
328:             * Find implementation of SPI.
329:             * 
330:             * @param spi Service Provider Interface Class.
331:             * 
332:             * @param properties Used to determine name of SPI implementation,
333:             *                   and passed to implementation.init() method if
334:             *                   implementation implements Service interface.
335:             * 
336:             * @param defaultImpl Default implementation.
337:             * 
338:             * @return Instance of a class implementing the SPI.
339:             * 
340:             * @exception DiscoveryException Thrown if the name of a class implementing
341:             *            the SPI cannot be found, if the class cannot be loaded and
342:             *            instantiated, or if the resulting class does not implement
343:             *            (or extend) the SPI.
344:             */
345:            public static Object find(ClassLoaders loaders, SPInterface spi,
346:                    PropertiesHolder properties, DefaultClassHolder defaultImpl)
347:                    throws DiscoveryException {
348:                ClassLoader contextLoader = JDKHooks.getJDKHooks()
349:                        .getThreadContextClassLoader();
350:
351:                Object obj = get(contextLoader, spi.getSPName());
352:
353:                if (obj == null) {
354:                    try {
355:                        obj = DiscoverClass.newInstance(loaders, spi,
356:                                properties, defaultImpl);
357:
358:                        if (obj != null) {
359:                            put(contextLoader, spi.getSPName(), obj);
360:                        }
361:                    } catch (DiscoveryException de) {
362:                        throw de;
363:                    } catch (Exception e) {
364:                        throw new DiscoveryException(
365:                                "Unable to instantiate implementation class for "
366:                                        + spi.getSPName(), e);
367:                    }
368:                }
369:
370:                return obj;
371:            }
372:
373:            /********************** CACHE-MANAGEMENT SUPPORT **********************/
374:
375:            /**
376:             * Release all internal references to previously created service
377:             * instances associated with the current thread context class loader.
378:             * The <code>release()</code> method is called for service instances that
379:             * implement the <code>Service</code> interface.
380:             *
381:             * This is useful in environments like servlet containers,
382:             * which implement application reloading by throwing away a ClassLoader.
383:             * Dangling references to objects in that class loader would prevent
384:             * garbage collection.
385:             */
386:            public static synchronized void release() {
387:                EnvironmentCache.release();
388:            }
389:
390:            /**
391:             * Release any internal references to a previously created service
392:             * instance associated with the current thread context class loader.
393:             * If the SPI instance implements <code>Service</code>, then call
394:             * <code>release()</code>.
395:             */
396:            public static synchronized void release(Class spiClass) {
397:                HashMap spis = (HashMap) EnvironmentCache.get(JDKHooks
398:                        .getJDKHooks().getThreadContextClassLoader());
399:
400:                if (spis != null) {
401:                    spis.remove(spiClass.getName());
402:                }
403:            }
404:
405:            /************************* SPI CACHE SUPPORT *************************
406:             * 
407:             * Cache services by a 'key' unique to the requesting class/environment:
408:             * 
409:             * When we 'release', it is expected that the caller of the 'release'
410:             * have the same thread context class loader... as that will be used
411:             * to identify all cached entries to be released.
412:             * 
413:             * We will manage synchronization directly, so all caches are implemented
414:             * as HashMap (unsynchronized).
415:             * 
416:             * - ClassLoader::groupContext::SPI::Instance Cache
417:             *         Cache : HashMap
418:             *         Key   : Thread Context Class Loader (<code>ClassLoader</code>).
419:             *         Value : groupContext::SPI Cache (<code>HashMap</code>).
420:             * 
421:             * - groupContext::SPI::Instance Cache
422:             *         Cache : HashMap
423:             *         Key   : groupContext (<code>String</code>).
424:             *         Value : SPI Cache (<code>HashMap</code>).
425:             * 
426:             * - SPI::Instance Cache
427:             *         Cache : HashMap
428:             *         Key   : SPI Class Name (<code>String</code>).
429:             *         Value : SPI Instance/Implementation (<code>Object</code>.
430:             */
431:
432:            /**
433:             * Implements first two levels of the cache (loader & groupContext).
434:             * Allows null keys, important as default groupContext is null.
435:             */
436:            // FIXME: Why is this here? All the methods used are static.
437:            //private static final EnvironmentCache root_cache = new EnvironmentCache();
438:            /**
439:             * Get service keyed by spi & classLoader.
440:             */
441:            private static synchronized Object get(ClassLoader classLoader,
442:                    String spiName) {
443:                HashMap spis = (HashMap) EnvironmentCache.get(classLoader);
444:
445:                return (spis != null) ? spis.get(spiName) : null;
446:            }
447:
448:            /**
449:             * Put service keyed by spi & classLoader.
450:             */
451:            private static synchronized void put(ClassLoader classLoader,
452:                    String spiName, Object service) {
453:                if (service != null) {
454:                    HashMap spis = (HashMap) EnvironmentCache.get(classLoader);
455:
456:                    if (spis == null) {
457:                        spis = new HashMap(EnvironmentCache.smallHashSize);
458:                        EnvironmentCache.put(classLoader, spis);
459:                    }
460:
461:                    spis.put(spiName, service);
462:                }
463:            }
464:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.