Source Code Cross Referenced for ServiceRegistry.java in  » 6.0-JDK-Core » image » javax » imageio » spi » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
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
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » image » javax.imageio.spi 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package javax.imageio.spi;
027
028        import java.io.File;
029        import java.util.ArrayList;
030        import java.util.HashMap;
031        import java.util.Iterator;
032        import java.util.List;
033        import java.util.Map;
034        import java.util.NoSuchElementException;
035        import java.util.Set;
036        import java.util.ServiceLoader;
037
038        /**
039         * A registry for service provider instances.
040         *
041         * <p> A <i>service</i> is a well-known set of interfaces and (usually
042         * abstract) classes.  A <i>service provider</i> is a specific
043         * implementation of a service.  The classes in a provider typically
044         * implement the interface or subclass the class defined by the
045         * service itself.
046         *
047         * <p> Service providers are stored in one or more <i>categories</i>,
048         * each of which is defined by a class of interface (described by a
049         * <code>Class</code> object) that all of its members must implement.
050         * The set of categories may be changed dynamically.
051         * 
052         * <p> Only a single instance of a given leaf class (that is, the
053         * actual class returned by <code>getClass()</code>, as opposed to any
054         * inherited classes or interfaces) may be registered.  That is,
055         * suppose that the
056         * <code>com.mycompany.mypkg.GreenServiceProvider</code> class
057         * implements the <code>com.mycompany.mypkg.MyService</code>
058         * interface.  If a <code>GreenServiceProvider</code> instance is
059         * registered, it will be stored in the category defined by the
060         * <code>MyService</code> class.  If a new instance of
061         * <code>GreenServiceProvider</code> is registered, it will replace
062         * the previous instance.  In practice, service provider objects are
063         * usually singletons so this behavior is appropriate.
064         *
065         * <p> To declare a service provider, a <code>services</code>
066         * subdirectory is placed within the <code>META-INF</code> directory
067         * that is present in every JAR file.  This directory contains a file
068         * for each service provider interface that has one or more
069         * implementation classes present in the JAR file.  For example, if
070         * the JAR file contained a class named
071         * <code>com.mycompany.mypkg.MyServiceImpl</code> which implements the
072         * <code>javax.someapi.SomeService</code> interface, the JAR file
073         * would contain a file named: <pre>
074         * META-INF/services/javax.someapi.SomeService </pre>
075         * 
076         * containing the line:
077         *
078         * <pre>
079         * com.mycompany.mypkg.MyService
080         * </pre>
081         *
082         * <p> The service provider classes should be to be lightweight and
083         * quick to load.  Implementations of these interfaces should avoid
084         * complex dependencies on other classes and on native code. The usual
085         * pattern for more complex services is to register a lightweight
086         * proxy for the heavyweight service.
087         *
088         * <p> An application may customize the contents of a registry as it
089         * sees fit, so long as it has the appropriate runtime permission.
090         *
091         * <p> For more details on declaring service providers, and the JAR
092         * format in general, see the <a
093         * href="../../../../technotes/guides/jar/jar.html">
094         * JAR File Specification</a>.
095         *
096         * @see RegisterableService
097         *
098         * @version 0.5
099         */
100        public class ServiceRegistry {
101
102            // Class -> Registry
103            private Map categoryMap = new HashMap();
104
105            /**
106             * Constructs a <code>ServiceRegistry</code> instance with a
107             * set of categories taken from the <code>categories</code>
108             * argument.
109             *
110             * @param categories an <code>Iterator</code> containing
111             * <code>Class</code> objects to be used to define categories.
112             *
113             * @exception IllegalArgumentException if
114             * <code>categories</code> is <code>null</code>.
115             */
116            public ServiceRegistry(Iterator<Class<?>> categories) {
117                if (categories == null) {
118                    throw new IllegalArgumentException("categories == null!");
119                }
120                while (categories.hasNext()) {
121                    Class category = (Class) categories.next();
122                    SubRegistry reg = new SubRegistry(this , category);
123                    categoryMap.put(category, reg);
124                }
125            }
126
127            // The following two methods expose functionality from
128            // sun.misc.Service.  If that class is made public, they may be
129            // removed.
130            // 
131            // The sun.misc.ServiceConfigurationError class may also be
132            // exposed, in which case the references to 'an
133            // <code>Error</code>' below should be changed to 'a
134            // <code>ServiceConfigurationError</code>'.
135
136            /**
137             * Searches for implementations of a particular service class
138             * using the given class loader.
139             *
140             * <p> This method transforms the name of the given service class
141             * into a provider-configuration filename as described in the
142             * class comment and then uses the <code>getResources</code>
143             * method of the given class loader to find all available files
144             * with that name.  These files are then read and parsed to
145             * produce a list of provider-class names.  The iterator that is
146             * returned uses the given class loader to look up and then
147             * instantiate each element of the list.
148             *
149             * <p> Because it is possible for extensions to be installed into
150             * a running Java virtual machine, this method may return
151             * different results each time it is invoked.
152             *
153             * @param providerClass a <code>Class</code>object indicating the
154             * class or interface of the service providers being detected.
155             *
156             * @param loader the class loader to be used to load
157             * provider-configuration files and instantiate provider classes,
158             * or <code>null</code> if the system class loader (or, failing that
159             * the bootstrap class loader) is to be used.
160             * 
161             * @return An <code>Iterator</code> that yields provider objects
162             * for the given service, in some arbitrary order.  The iterator
163             * will throw an <code>Error</code> if a provider-configuration
164             * file violates the specified format or if a provider class
165             * cannot be found and instantiated.
166             *
167             * @exception IllegalArgumentException if
168             * <code>providerClass</code> is <code>null</code>.
169             */
170            public static <T> Iterator<T> lookupProviders(
171                    Class<T> providerClass, ClassLoader loader) {
172                if (providerClass == null) {
173                    throw new IllegalArgumentException("providerClass == null!");
174                }
175                return ServiceLoader.load(providerClass, loader).iterator();
176            }
177
178            /**
179             * Locates and incrementally instantiates the available providers
180             * of a given service using the context class loader.  This
181             * convenience method is equivalent to:
182             *
183             * <pre>
184             *   ClassLoader cl = Thread.currentThread().getContextClassLoader();
185             *   return Service.providers(service, cl);
186             * </pre>
187             *
188             * @param providerClass a <code>Class</code>object indicating the
189             * class or interface of the service providers being detected.
190             *
191             * @return An <code>Iterator</code> that yields provider objects
192             * for the given service, in some arbitrary order.  The iterator
193             * will throw an <code>Error</code> if a provider-configuration
194             * file violates the specified format or if a provider class
195             * cannot be found and instantiated.
196             *
197             * @exception IllegalArgumentException if
198             * <code>providerClass</code> is <code>null</code>.
199             */
200            public static <T> Iterator<T> lookupProviders(Class<T> providerClass) {
201                if (providerClass == null) {
202                    throw new IllegalArgumentException("providerClass == null!");
203                }
204                return ServiceLoader.load(providerClass).iterator();
205            }
206
207            /**
208             * Returns an <code>Iterator</code> of <code>Class</code> objects
209             * indicating the current set of categories.  The iterator will be
210             * empty if no categories exist.
211             *
212             * @return an <code>Iterator</code> containing
213             * <code>Class</code>objects.
214             */
215            public Iterator<Class<?>> getCategories() {
216                Set keySet = categoryMap.keySet();
217                return keySet.iterator();
218            }
219
220            /**
221             * Returns an Iterator containing the subregistries to which the
222             * provider belongs.
223             */
224            private Iterator getSubRegistries(Object provider) {
225                List l = new ArrayList();
226                Iterator iter = categoryMap.keySet().iterator();
227                while (iter.hasNext()) {
228                    Class c = (Class) iter.next();
229                    if (c.isAssignableFrom(provider.getClass())) {
230                        l.add((SubRegistry) categoryMap.get(c));
231                    }
232                }
233                return l.iterator();
234            }
235
236            /**
237             * Adds a service provider object to the registry.  The provider
238             * is associated with the given category.
239             *
240             * <p> If <code>provider</code> implements the
241             * <code>RegisterableService</code> interface, its
242             * <code>onRegistration</code> method will be called.  Its
243             * <code>onDeregistration</code> method will be called each time
244             * it is deregistered from a category, for example if a
245             * category is removed or the registry is garbage collected.
246             *
247             * @param provider the service provide object to be registered.
248             * @param category the category under which to register the
249             * provider.
250             *
251             * @return true if no provider of the same class was previously
252             * registered in the same category category.
253             *
254             * @exception IllegalArgumentException if <code>provider</code> is
255             * <code>null</code>.
256             * @exception IllegalArgumentException if there is no category
257             * corresponding to <code>category</code>.
258             * @exception ClassCastException if provider does not implement
259             * the <code>Class</code> defined by <code>category</code>.
260             */
261            public <T> boolean registerServiceProvider(T provider,
262                    Class<T> category) {
263                if (provider == null) {
264                    throw new IllegalArgumentException("provider == null!");
265                }
266                SubRegistry reg = (SubRegistry) categoryMap.get(category);
267                if (reg == null) {
268                    throw new IllegalArgumentException("category unknown!");
269                }
270                if (!category.isAssignableFrom(provider.getClass())) {
271                    throw new ClassCastException();
272                }
273
274                return reg.registerServiceProvider(provider);
275            }
276
277            /**
278             * Adds a service provider object to the registry.  The provider
279             * is associated within each category present in the registry
280             * whose <code>Class</code> it implements.
281             *
282             * <p> If <code>provider</code> implements the
283             * <code>RegisterableService</code> interface, its
284             * <code>onRegistration</code> method will be called once for each
285             * category it is registered under.  Its
286             * <code>onDeregistration</code> method will be called each time
287             * it is deregistered from a category or when the registry is
288             * finalized.
289             *
290             * @param provider the service provider object to be registered.
291             *
292             * @exception IllegalArgumentException if
293             * <code>provider</code> is <code>null</code>.
294             */
295            public void registerServiceProvider(Object provider) {
296                if (provider == null) {
297                    throw new IllegalArgumentException("provider == null!");
298                }
299                Iterator regs = getSubRegistries(provider);
300                while (regs.hasNext()) {
301                    SubRegistry reg = (SubRegistry) regs.next();
302                    reg.registerServiceProvider(provider);
303                }
304            }
305
306            /**
307             * Adds a set of service provider objects, taken from an
308             * <code>Iterator</code> to the registry.  Each provider is
309             * associated within each category present in the registry whose
310             * <code>Class</code> it implements.
311             *
312             * <p> For each entry of <code>providers</code> that implements
313             * the <code>RegisterableService</code> interface, its
314             * <code>onRegistration</code> method will be called once for each
315             * category it is registered under.  Its
316             * <code>onDeregistration</code> method will be called each time
317             * it is deregistered from a category or when the registry is
318             * finalized.
319             *
320             * @param providers an Iterator containing service provider
321             * objects to be registered.
322             *
323             * @exception IllegalArgumentException if <code>providers</code>
324             * is <code>null</code> or contains a <code>null</code> entry.
325             */
326            public void registerServiceProviders(Iterator<?> providers) {
327                if (providers == null) {
328                    throw new IllegalArgumentException("provider == null!");
329                }
330                while (providers.hasNext()) {
331                    registerServiceProvider(providers.next());
332                }
333            }
334
335            /**
336             * Removes a service provider object from the given category.  If
337             * the provider was not previously registered, nothing happens and
338             * <code>false</code> is returned.  Otherwise, <code>true</code>
339             * is returned.  If an object of the same class as
340             * <code>provider</code> but not equal (using <code>==</code>) to
341             * <code>provider</code> is registered, it will not be
342             * deregistered.
343             *
344             * <p> If <code>provider</code> implements the
345             * <code>RegisterableService</code> interface, its
346             * <code>onDeregistration</code> method will be called.
347             *
348             * @param provider the service provider object to be deregistered.
349             * @param category the category from which to deregister the
350             * provider.
351             *
352             * @return <code>true</code> if the provider was previously
353             * registered in the same category category,
354             * <code>false</code> otherwise.
355             *
356             * @exception IllegalArgumentException if <code>provider</code> is
357             * <code>null</code>.
358             * @exception IllegalArgumentException if there is no category
359             * corresponding to <code>category</code>.
360             * @exception ClassCastException if provider does not implement
361             * the class defined by <code>category</code>.
362             */
363            public <T> boolean deregisterServiceProvider(T provider,
364                    Class<T> category) {
365                if (provider == null) {
366                    throw new IllegalArgumentException("provider == null!");
367                }
368                SubRegistry reg = (SubRegistry) categoryMap.get(category);
369                if (reg == null) {
370                    throw new IllegalArgumentException("category unknown!");
371                }
372                if (!category.isAssignableFrom(provider.getClass())) {
373                    throw new ClassCastException();
374                }
375                return reg.deregisterServiceProvider(provider);
376            }
377
378            /**
379             * Removes a service provider object from all categories that
380             * contain it.
381             *
382             * @param provider the service provider object to be deregistered.
383             *
384             * @exception IllegalArgumentException if <code>provider</code> is
385             * <code>null</code>.
386             */
387            public void deregisterServiceProvider(Object provider) {
388                if (provider == null) {
389                    throw new IllegalArgumentException("provider == null!");
390                }
391                Iterator regs = getSubRegistries(provider);
392                while (regs.hasNext()) {
393                    SubRegistry reg = (SubRegistry) regs.next();
394                    reg.deregisterServiceProvider(provider);
395                }
396            }
397
398            /**
399             * Returns <code>true</code> if <code>provider</code> is currently
400             * registered.
401             *
402             * @param provider the service provider object to be queried.
403             *
404             * @return <code>true</code> if the given provider has been
405             * registered.
406             *
407             * @exception IllegalArgumentException if <code>provider</code> is
408             * <code>null</code>.
409             */
410            public boolean contains(Object provider) {
411                if (provider == null) {
412                    throw new IllegalArgumentException("provider == null!");
413                }
414                Iterator regs = getSubRegistries(provider);
415                while (regs.hasNext()) {
416                    SubRegistry reg = (SubRegistry) regs.next();
417                    if (reg.contains(provider)) {
418                        return true;
419                    }
420                }
421
422                return false;
423            }
424
425            /**
426             * Returns an <code>Iterator</code> containing all registered
427             * service providers in the given category.  If
428             * <code>useOrdering</code> is <code>false</code>, the iterator
429             * will return all of the server provider objects in an arbitrary
430             * order.  Otherwise, the ordering will respect any pairwise
431             * orderings that have been set.  If the graph of pairwise
432             * orderings contains cycles, any providers that belong to a cycle
433             * will not be returned.
434             *
435             * @param category the category to be retrieved from.
436             * @param useOrdering <code>true</code> if pairwise orderings
437             * should be taken account in ordering the returned objects.
438             *
439             * @return an <code>Iterator</code> containing service provider
440             * objects from the given category, possibly in order.
441             *
442             * @exception IllegalArgumentException if there is no category
443             * corresponding to <code>category</code>.
444             */
445            public <T> Iterator<T> getServiceProviders(Class<T> category,
446                    boolean useOrdering) {
447                SubRegistry reg = (SubRegistry) categoryMap.get(category);
448                if (reg == null) {
449                    throw new IllegalArgumentException("category unknown!");
450                }
451                return reg.getServiceProviders(useOrdering);
452            }
453
454            /**
455             * A simple filter interface used by
456             * <code>ServiceRegistry.getServiceProviders</code> to select
457             * providers matching an arbitrary criterion.  Classes that
458             * implement this interface should be defined in order to make use
459             * of the <code>getServiceProviders</code> method of
460             * <code>ServiceRegistry</code> that takes a <code>Filter</code>.
461             *
462             * @see ServiceRegistry#getServiceProviders(Class, ServiceRegistry.Filter, boolean)
463             */
464            public interface Filter {
465
466                /**
467                 * Returns <code>true</code> if the given
468                 * <code>provider</code> object matches the criterion defined
469                 * by this <code>Filter</code>.
470                 *
471                 * @param provider a service provider <code>Object</code>.
472                 *
473                 * @return true if the provider matches the criterion.
474                 */
475                boolean filter(Object provider);
476            }
477
478            /**
479             * Returns an <code>Iterator</code> containing service provider
480             * objects within a given category that satisfy a criterion
481             * imposed by the supplied <code>ServiceRegistry.Filter</code>
482             * object's <code>filter</code> method.
483             *
484             * <p> The <code>useOrdering</code> argument controls the
485             * ordering of the results using the same rules as
486             * <code>getServiceProviders(Class, boolean)</code>.
487             *
488             * @param category the category to be retrieved from.
489             * @param filter an instance of <code>ServiceRegistry.Filter</code>
490             * whose <code>filter</code> method will be invoked.
491             * @param useOrdering <code>true</code> if pairwise orderings
492             * should be taken account in ordering the returned objects.
493             *
494             * @return an <code>Iterator</code> containing service provider
495             * objects from the given category, possibly in order.
496             *
497             * @exception IllegalArgumentException if there is no category
498             * corresponding to <code>category</code>.
499             */
500            public <T> Iterator<T> getServiceProviders(Class<T> category,
501                    Filter filter, boolean useOrdering) {
502                SubRegistry reg = (SubRegistry) categoryMap.get(category);
503                if (reg == null) {
504                    throw new IllegalArgumentException("category unknown!");
505                }
506                Iterator iter = getServiceProviders(category, useOrdering);
507                return new FilterIterator(iter, filter);
508            }
509
510            /**
511             * Returns the currently registered service provider object that
512             * is of the given class type.  At most one object of a given
513             * class is allowed to be registered at any given time.  If no
514             * registered object has the desired class type, <code>null</code>
515             * is returned.
516             *
517             * @param providerClass the <code>Class</code> of the desired
518             * service provider object.
519             *
520             * @return a currently registered service provider object with the
521             * desired <code>Class</code>type, or <code>null</code> is none is
522             * present.
523             *
524             * @exception IllegalArgumentException if <code>providerClass</code> is
525             * <code>null</code>.
526             */
527            public <T> T getServiceProviderByClass(Class<T> providerClass) {
528                if (providerClass == null) {
529                    throw new IllegalArgumentException("providerClass == null!");
530                }
531                Iterator iter = categoryMap.keySet().iterator();
532                while (iter.hasNext()) {
533                    Class c = (Class) iter.next();
534                    if (c.isAssignableFrom(providerClass)) {
535                        SubRegistry reg = (SubRegistry) categoryMap.get(c);
536                        T provider = reg
537                                .getServiceProviderByClass(providerClass);
538                        if (provider != null) {
539                            return provider;
540                        }
541                    }
542                }
543                return null;
544            }
545
546            /**
547             * Sets a pairwise ordering between two service provider objects
548             * within a given category.  If one or both objects are not
549             * currently registered within the given category, or if the
550             * desired ordering is already set, nothing happens and
551             * <code>false</code> is returned.  If the providers previously
552             * were ordered in the reverse direction, that ordering is
553             * removed.
554             *
555             * <p> The ordering will be used by the
556             * <code>getServiceProviders</code> methods when their
557             * <code>useOrdering</code> argument is <code>true</code>.
558             *
559             * @param category a <code>Class</code> object indicating the
560             * category under which the preference is to be established.
561             * @param firstProvider the preferred provider.
562             * @param secondProvider the provider to which
563             * <code>firstProvider</code> is preferred.
564             *
565             * @return <code>true</code> if a previously unset ordering
566             * was established.
567             *
568             * @exception IllegalArgumentException if either provider is
569             * <code>null</code> or they are the same object.
570             * @exception IllegalArgumentException if there is no category
571             * corresponding to <code>category</code>.
572             */
573            public <T> boolean setOrdering(Class<T> category, T firstProvider,
574                    T secondProvider) {
575                if (firstProvider == null || secondProvider == null) {
576                    throw new IllegalArgumentException("provider is null!");
577                }
578                if (firstProvider == secondProvider) {
579                    throw new IllegalArgumentException(
580                            "providers are the same!");
581                }
582                SubRegistry reg = (SubRegistry) categoryMap.get(category);
583                if (reg == null) {
584                    throw new IllegalArgumentException("category unknown!");
585                }
586                if (reg.contains(firstProvider) && reg.contains(secondProvider)) {
587                    return reg.setOrdering(firstProvider, secondProvider);
588                }
589                return false;
590            }
591
592            /**
593             * Sets a pairwise ordering between two service provider objects
594             * within a given category.  If one or both objects are not
595             * currently registered within the given category, or if no
596             * ordering is currently set between them, nothing happens
597             * and <code>false</code> is returned.
598             *
599             * <p> The ordering will be used by the
600             * <code>getServiceProviders</code> methods when their
601             * <code>useOrdering</code> argument is <code>true</code>.
602             *
603             * @param category a <code>Class</code> object indicating the
604             * category under which the preference is to be disestablished.
605             * @param firstProvider the formerly preferred provider.
606             * @param secondProvider the provider to which
607             * <code>firstProvider</code> was formerly preferred.
608             *
609             * @return <code>true</code> if a previously set ordering was
610             * disestablished.
611             *
612             * @exception IllegalArgumentException if either provider is
613             * <code>null</code> or they are the same object.
614             * @exception IllegalArgumentException if there is no category
615             * corresponding to <code>category</code>.
616             */
617            public <T> boolean unsetOrdering(Class<T> category,
618                    T firstProvider, T secondProvider) {
619                if (firstProvider == null || secondProvider == null) {
620                    throw new IllegalArgumentException("provider is null!");
621                }
622                if (firstProvider == secondProvider) {
623                    throw new IllegalArgumentException(
624                            "providers are the same!");
625                }
626                SubRegistry reg = (SubRegistry) categoryMap.get(category);
627                if (reg == null) {
628                    throw new IllegalArgumentException("category unknown!");
629                }
630                if (reg.contains(firstProvider) && reg.contains(secondProvider)) {
631                    return reg.unsetOrdering(firstProvider, secondProvider);
632                }
633                return false;
634            }
635
636            /**
637             * Deregisters all service provider object currently registered
638             * under the given category.
639             *
640             * @param category the category to be emptied.
641             *
642             * @exception IllegalArgumentException if there is no category
643             * corresponding to <code>category</code>.
644             */
645            public void deregisterAll(Class<?> category) {
646                SubRegistry reg = (SubRegistry) categoryMap.get(category);
647                if (reg == null) {
648                    throw new IllegalArgumentException("category unknown!");
649                }
650                reg.clear();
651            }
652
653            /**
654             * Deregisters all currently registered service providers from all
655             * categories.
656             */
657            public void deregisterAll() {
658                Iterator iter = categoryMap.values().iterator();
659                while (iter.hasNext()) {
660                    SubRegistry reg = (SubRegistry) iter.next();
661                    reg.clear();
662                }
663            }
664
665            /**
666             * Finalizes this object prior to garbage collection.  The
667             * <code>deregisterAll</code> method is called to deregister all
668             * currently registered service providers.  This method should not
669             * be called from application code.
670             *
671             * @exception Throwable if an error occurs during superclass
672             * finalization.
673             */
674            public void finalize() throws Throwable {
675                deregisterAll();
676                super .finalize();
677            }
678        }
679
680        /**
681         * A portion of a registry dealing with a single superclass or
682         * interface.
683         */
684        class SubRegistry {
685
686            ServiceRegistry registry;
687
688            Class category;
689
690            // Provider Objects organized by partial oridering
691            PartiallyOrderedSet poset = new PartiallyOrderedSet();
692
693            // Class -> Provider Object of that class
694            Map<Class<?>, Object> map = new HashMap();
695
696            public SubRegistry(ServiceRegistry registry, Class category) {
697                this .registry = registry;
698                this .category = category;
699            }
700
701            public boolean registerServiceProvider(Object provider) {
702                Object oprovider = map.get(provider.getClass());
703                boolean present = oprovider != null;
704
705                if (present) {
706                    deregisterServiceProvider(oprovider);
707                }
708                map.put(provider.getClass(), provider);
709                poset.add(provider);
710                if (provider instanceof  RegisterableService) {
711                    RegisterableService rs = (RegisterableService) provider;
712                    rs.onRegistration(registry, category);
713                }
714
715                return !present;
716            }
717
718            /**
719             * If the provider was not previously registered, do nothing.
720             * 
721             * @return true if the provider was previously registered.
722             */
723            public boolean deregisterServiceProvider(Object provider) {
724                Object oprovider = map.get(provider.getClass());
725
726                if (provider == oprovider) {
727                    map.remove(provider.getClass());
728                    poset.remove(provider);
729                    if (provider instanceof  RegisterableService) {
730                        RegisterableService rs = (RegisterableService) provider;
731                        rs.onDeregistration(registry, category);
732                    }
733
734                    return true;
735                }
736                return false;
737            }
738
739            public boolean contains(Object provider) {
740                Object oprovider = map.get(provider.getClass());
741                return oprovider == provider;
742            }
743
744            public boolean setOrdering(Object firstProvider,
745                    Object secondProvider) {
746                return poset.setOrdering(firstProvider, secondProvider);
747            }
748
749            public boolean unsetOrdering(Object firstProvider,
750                    Object secondProvider) {
751                return poset.unsetOrdering(firstProvider, secondProvider);
752            }
753
754            public Iterator getServiceProviders(boolean useOrdering) {
755                if (useOrdering) {
756                    return poset.iterator();
757                } else {
758                    return map.values().iterator();
759                }
760            }
761
762            public <T> T getServiceProviderByClass(Class<T> providerClass) {
763                return (T) map.get(providerClass);
764            }
765
766            public void clear() {
767                Iterator iter = map.values().iterator();
768                while (iter.hasNext()) {
769                    Object provider = iter.next();
770                    iter.remove();
771
772                    if (provider instanceof  RegisterableService) {
773                        RegisterableService rs = (RegisterableService) provider;
774                        rs.onDeregistration(registry, category);
775                    }
776                }
777                poset.clear();
778            }
779
780            public void finalize() {
781                clear();
782            }
783        }
784
785        /**
786         * A class for wrapping <code>Iterators</code> with a filter function.
787         * This provides an iterator for a subset without duplication.
788         */
789        class FilterIterator<T> implements  Iterator<T> {
790
791            private Iterator<T> iter;
792            private ServiceRegistry.Filter filter;
793
794            private T next = null;
795
796            public FilterIterator(Iterator<T> iter,
797                    ServiceRegistry.Filter filter) {
798                this .iter = iter;
799                this .filter = filter;
800                advance();
801            }
802
803            private void advance() {
804                while (iter.hasNext()) {
805                    T elt = iter.next();
806                    if (filter.filter(elt)) {
807                        next = elt;
808                        return;
809                    }
810                }
811
812                next = null;
813            }
814
815            public boolean hasNext() {
816                return next != null;
817            }
818
819            public T next() {
820                if (next == null) {
821                    throw new NoSuchElementException();
822                }
823                T o = next;
824                advance();
825                return o;
826            }
827
828            public void remove() {
829                throw new UnsupportedOperationException();
830            }
831        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.