Source Code Cross Referenced for ServiceLoader.java in  » 6.0-JDK-Core » Collections-Jar-Zip-Logging-regex » java » util » 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 » Collections Jar Zip Logging regex » java.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 2005-2006 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 java.util;
027
028        import java.io.BufferedReader;
029        import java.io.IOException;
030        import java.io.InputStream;
031        import java.io.InputStreamReader;
032        import java.net.URL;
033        import java.util.ArrayList;
034        import java.util.Enumeration;
035        import java.util.Iterator;
036        import java.util.List;
037        import java.util.NoSuchElementException;
038
039        /**
040         * A simple service-provider loading facility.
041         *
042         * <p> A <i>service</i> is a well-known set of interfaces and (usually
043         * abstract) classes.  A <i>service provider</i> is a specific implementation
044         * of a service.  The classes in a provider typically implement the interfaces
045         * and subclass the classes defined in the service itself.  Service providers
046         * can be installed in an implementation of the Java platform in the form of
047         * extensions, that is, jar files placed into any of the usual extension
048         * directories.  Providers can also be made available by adding them to the
049         * application's class path or by some other platform-specific means.
050         *
051         * <p> For the purpose of loading, a service is represented by a single type,
052         * that is, a single interface or abstract class.  (A concrete class can be
053         * used, but this is not recommended.)  A provider of a given service contains
054         * one or more concrete classes that extend this <i>service type</i> with data
055         * and code specific to the provider.  The <i>provider class</i> is typically
056         * not the entire provider itself but rather a proxy which contains enough
057         * information to decide whether the provider is able to satisfy a particular
058         * request together with code that can create the actual provider on demand.
059         * The details of provider classes tend to be highly service-specific; no
060         * single class or interface could possibly unify them, so no such type is
061         * defined here.  The only requirement enforced by this facility is that
062         * provider classes must have a zero-argument constructor so that they can be
063         * instantiated during loading.
064         *
065         * <p><a name="format"> A service provider is identified by placing a
066         * <i>provider-configuration file</i> in the resource directory
067         * <tt>META-INF/services</tt>.  The file's name is the fully-qualified <a
068         * href="../lang/ClassLoader.html#name">binary name</a> of the service's type.
069         * The file contains a list of fully-qualified binary names of concrete
070         * provider classes, one per line.  Space and tab characters surrounding each
071         * name, as well as blank lines, are ignored.  The comment character is
072         * <tt>'#'</tt> (<tt>'&#92;u0023'</tt>, <font size="-1">NUMBER SIGN</font>); on
073         * each line all characters following the first comment character are ignored.
074         * The file must be encoded in UTF-8.
075         *
076         * <p> If a particular concrete provider class is named in more than one
077         * configuration file, or is named in the same configuration file more than
078         * once, then the duplicates are ignored.  The configuration file naming a
079         * particular provider need not be in the same jar file or other distribution
080         * unit as the provider itself.  The provider must be accessible from the same
081         * class loader that was initially queried to locate the configuration file;
082         * note that this is not necessarily the class loader from which the file was
083         * actually loaded.
084         *
085         * <p> Providers are located and instantiated lazily, that is, on demand.  A
086         * service loader maintains a cache of the providers that have been loaded so
087         * far.  Each invocation of the {@link #iterator iterator} method returns an
088         * iterator that first yields all of the elements of the cache, in
089         * instantiation order, and then lazily locates and instantiates any remaining
090         * providers, adding each one to the cache in turn.  The cache can be cleared
091         * via the {@link #reload reload} method.
092         *
093         * <p> Service loaders always execute in the security context of the caller.
094         * Trusted system code should typically invoke the methods in this class, and
095         * the methods of the iterators which they return, from within a privileged
096         * security context.
097         *
098         * <p> Instances of this class are not safe for use by multiple concurrent
099         * threads.
100         *
101         * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
102         * method in this class will cause a {@link NullPointerException} to be thrown.
103         *
104         *
105         * <p><span style="font-weight: bold; padding-right: 1em">Example</span>
106         * Suppose we have a service type <tt>com.example.CodecSet</tt> which is
107         * intended to represent sets of encoder/decoder pairs for some protocol.  In
108         * this case it is an abstract class with two abstract methods:
109         *
110         * <blockquote><pre>
111         * public abstract Encoder getEncoder(String encodingName);
112         * public abstract Decoder getDecoder(String encodingName);</pre></blockquote>
113         *
114         * Each method returns an appropriate object or <tt>null</tt> if the provider
115         * does not support the given encoding.  Typical providers support more than
116         * one encoding.
117         *
118         * <p> If <tt>com.example.impl.StandardCodecs</tt> is an implementation of the
119         * <tt>CodecSet</tt> service then its jar file also contains a file named
120         *
121         * <blockquote><pre>
122         * META-INF/services/com.example.CodecSet</pre></blockquote>
123         *
124         * <p> This file contains the single line:
125         *
126         * <blockquote><pre>
127         * com.example.impl.StandardCodecs    # Standard codecs</pre></blockquote>
128         *
129         * <p> The <tt>CodecSet</tt> class creates and saves a single service instance
130         * at initialization:
131         *
132         * <blockquote><pre>
133         * private static ServiceLoader&lt;CodecSet&gt; codecSetLoader
134         *     = ServiceLoader.load(CodecSet.class);</pre></blockquote>
135         *
136         * <p> To locate an encoder for a given encoding name it defines a static
137         * factory method which iterates through the known and available providers,
138         * returning only when it has located a suitable encoder or has run out of
139         * providers.
140         *
141         * <blockquote><pre>
142         * public static Encoder getEncoder(String encodingName) {
143         *     for (CodecSet cp : codecSetLoader) {
144         *         Encoder enc = cp.getEncoder(encodingName);
145         *         if (enc != null)
146         *             return enc;
147         *     }
148         *     return null;
149         * }</pre></blockquote>
150         *
151         * <p> A <tt>getDecoder</tt> method is defined similarly.
152         *
153         *
154         * <p><span style="font-weight: bold; padding-right: 1em">Usage Note</span> If
155         * the class path of a class loader that is used for provider loading includes
156         * remote network URLs then those URLs will be dereferenced in the process of
157         * searching for provider-configuration files.
158         *
159         * <p> This activity is normal, although it may cause puzzling entries to be
160         * created in web-server logs.  If a web server is not configured correctly,
161         * however, then this activity may cause the provider-loading algorithm to fail
162         * spuriously.
163         *
164         * <p> A web server should return an HTTP 404 (Not Found) response when a
165         * requested resource does not exist.  Sometimes, however, web servers are
166         * erroneously configured to return an HTTP 200 (OK) response along with a
167         * helpful HTML error page in such cases.  This will cause a {@link
168         * ServiceConfigurationError} to be thrown when this class attempts to parse
169         * the HTML page as a provider-configuration file.  The best solution to this
170         * problem is to fix the misconfigured web server to return the correct
171         * response code (HTTP 404) along with the HTML error page.
172         *
173         * @param  <S>
174         *         The type of the service to be loaded by this loader
175         *
176         * @author Mark Reinhold
177         * @version 1.16, 07/05/05
178         * @since 1.6
179         */
180
181        public final class ServiceLoader<S> implements  Iterable<S> {
182
183            private static final String PREFIX = "META-INF/services/";
184
185            // The class or interface representing the service being loaded
186            private Class<S> service;
187
188            // The class loader used to locate, load, and instantiate providers
189            private ClassLoader loader;
190
191            // Cached providers, in instantiation order
192            private LinkedHashMap<String, S> providers = new LinkedHashMap<String, S>();
193
194            // The current lazy-lookup iterator
195            private LazyIterator lookupIterator;
196
197            /**
198             * Clear this loader's provider cache so that all providers will be
199             * reloaded.
200             *
201             * <p> After invoking this method, subsequent invocations of the {@link
202             * #iterator() iterator} method will lazily look up and instantiate
203             * providers from scratch, just as is done by a newly-created loader.
204             *
205             * <p> This method is intended for use in situations in which new providers
206             * can be installed into a running Java virtual machine.
207             */
208            public void reload() {
209                providers.clear();
210                lookupIterator = new LazyIterator(service, loader);
211            }
212
213            private ServiceLoader(Class<S> svc, ClassLoader cl) {
214                service = svc;
215                loader = cl;
216                reload();
217            }
218
219            private static void fail(Class service, String msg, Throwable cause)
220                    throws ServiceConfigurationError {
221                throw new ServiceConfigurationError(service.getName() + ": "
222                        + msg, cause);
223            }
224
225            private static void fail(Class service, String msg)
226                    throws ServiceConfigurationError {
227                throw new ServiceConfigurationError(service.getName() + ": "
228                        + msg);
229            }
230
231            private static void fail(Class service, URL u, int line, String msg)
232                    throws ServiceConfigurationError {
233                fail(service, u + ":" + line + ": " + msg);
234            }
235
236            // Parse a single line from the given configuration file, adding the name
237            // on the line to the names list.
238            //
239            private int parseLine(Class service, URL u, BufferedReader r,
240                    int lc, List<String> names) throws IOException,
241                    ServiceConfigurationError {
242                String ln = r.readLine();
243                if (ln == null) {
244                    return -1;
245                }
246                int ci = ln.indexOf('#');
247                if (ci >= 0)
248                    ln = ln.substring(0, ci);
249                ln = ln.trim();
250                int n = ln.length();
251                if (n != 0) {
252                    if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
253                        fail(service, u, lc,
254                                "Illegal configuration-file syntax");
255                    int cp = ln.codePointAt(0);
256                    if (!Character.isJavaIdentifierStart(cp))
257                        fail(service, u, lc, "Illegal provider-class name: "
258                                + ln);
259                    for (int i = Character.charCount(cp); i < n; i += Character
260                            .charCount(cp)) {
261                        cp = ln.codePointAt(i);
262                        if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
263                            fail(service, u, lc,
264                                    "Illegal provider-class name: " + ln);
265                    }
266                    if (!providers.containsKey(ln) && !names.contains(ln))
267                        names.add(ln);
268                }
269                return lc + 1;
270            }
271
272            // Parse the content of the given URL as a provider-configuration file.
273            //
274            // @param  service
275            //         The service type for which providers are being sought;
276            //         used to construct error detail strings
277            //
278            // @param  u
279            //         The URL naming the configuration file to be parsed
280            //
281            // @return A (possibly empty) iterator that will yield the provider-class
282            //         names in the given configuration file that are not yet members
283            //         of the returned set
284            //
285            // @throws ServiceConfigurationError
286            //         If an I/O error occurs while reading from the given URL, or
287            //         if a configuration-file format error is detected
288            //
289            private Iterator<String> parse(Class service, URL u)
290                    throws ServiceConfigurationError {
291                InputStream in = null;
292                BufferedReader r = null;
293                ArrayList<String> names = new ArrayList<String>();
294                try {
295                    in = u.openStream();
296                    r = new BufferedReader(new InputStreamReader(in, "utf-8"));
297                    int lc = 1;
298                    while ((lc = parseLine(service, u, r, lc, names)) >= 0)
299                        ;
300                } catch (IOException x) {
301                    fail(service, "Error reading configuration file", x);
302                } finally {
303                    try {
304                        if (r != null)
305                            r.close();
306                        if (in != null)
307                            in.close();
308                    } catch (IOException y) {
309                        fail(service, "Error closing configuration file", y);
310                    }
311                }
312                return names.iterator();
313            }
314
315            // Private inner class implementing fully-lazy provider lookup
316            //
317            private class LazyIterator implements  Iterator<S> {
318
319                Class<S> service;
320                ClassLoader loader;
321                Enumeration<URL> configs = null;
322                Iterator<String> pending = null;
323                String nextName = null;
324
325                private LazyIterator(Class<S> service, ClassLoader loader) {
326                    this .service = service;
327                    this .loader = loader;
328                }
329
330                public boolean hasNext() {
331                    if (nextName != null) {
332                        return true;
333                    }
334                    if (configs == null) {
335                        try {
336                            String fullName = PREFIX + service.getName();
337                            if (loader == null)
338                                configs = ClassLoader
339                                        .getSystemResources(fullName);
340                            else
341                                configs = loader.getResources(fullName);
342                        } catch (IOException x) {
343                            fail(service, "Error locating configuration files",
344                                    x);
345                        }
346                    }
347                    while ((pending == null) || !pending.hasNext()) {
348                        if (!configs.hasMoreElements()) {
349                            return false;
350                        }
351                        pending = parse(service, configs.nextElement());
352                    }
353                    nextName = pending.next();
354                    return true;
355                }
356
357                public S next() {
358                    if (!hasNext()) {
359                        throw new NoSuchElementException();
360                    }
361                    String cn = nextName;
362                    nextName = null;
363                    try {
364                        S p = service.cast(Class.forName(cn, true, loader)
365                                .newInstance());
366                        providers.put(cn, p);
367                        return p;
368                    } catch (ClassNotFoundException x) {
369                        fail(service, "Provider " + cn + " not found");
370                    } catch (Throwable x) {
371                        fail(service, "Provider " + cn
372                                + " could not be instantiated: " + x, x);
373                    }
374                    throw new Error(); // This cannot happen
375                }
376
377                public void remove() {
378                    throw new UnsupportedOperationException();
379                }
380
381            }
382
383            /**
384             * Lazily loads the available providers of this loader's service.
385             *
386             * <p> The iterator returned by this method first yields all of the
387             * elements of the provider cache, in instantiation order.  It then lazily
388             * loads and instantiates any remaining providers, adding each one to the
389             * cache in turn.
390             *
391             * <p> To achieve laziness the actual work of parsing the available
392             * provider-configuration files and instantiating providers must be done by
393             * the iterator itself.  Its {@link java.util.Iterator#hasNext hasNext} and
394             * {@link java.util.Iterator#next next} methods can therefore throw a
395             * {@link ServiceConfigurationError} if a provider-configuration file
396             * violates the specified format, or if it names a provider class that
397             * cannot be found and instantiated, or if the result of instantiating the
398             * class is not assignable to the service type, or if any other kind of
399             * exception or error is thrown as the next provider is located and
400             * instantiated.  To write robust code it is only necessary to catch {@link
401             * ServiceConfigurationError} when using a service iterator.
402             *
403             * <p> If such an error is thrown then subsequent invocations of the
404             * iterator will make a best effort to locate and instantiate the next
405             * available provider, but in general such recovery cannot be guaranteed.
406             *
407             * <blockquote style="font-size: smaller; line-height: 1.2"><span
408             * style="padding-right: 1em; font-weight: bold">Design Note</span>
409             * Throwing an error in these cases may seem extreme.  The rationale for
410             * this behavior is that a malformed provider-configuration file, like a
411             * malformed class file, indicates a serious problem with the way the Java
412             * virtual machine is configured or is being used.  As such it is
413             * preferable to throw an error rather than try to recover or, even worse,
414             * fail silently.</blockquote>
415             *
416             * <p> The iterator returned by this method does not support removal.
417             * Invoking its {@link java.util.Iterator#remove() remove} method will
418             * cause an {@link UnsupportedOperationException} to be thrown.
419             *
420             * @return  An iterator that lazily loads providers for this loader's
421             *          service
422             */
423            public Iterator<S> iterator() {
424                return new Iterator<S>() {
425
426                    Iterator<Map.Entry<String, S>> knownProviders = providers
427                            .entrySet().iterator();
428
429                    public boolean hasNext() {
430                        if (knownProviders.hasNext())
431                            return true;
432                        return lookupIterator.hasNext();
433                    }
434
435                    public S next() {
436                        if (knownProviders.hasNext())
437                            return knownProviders.next().getValue();
438                        return lookupIterator.next();
439                    }
440
441                    public void remove() {
442                        throw new UnsupportedOperationException();
443                    }
444
445                };
446            }
447
448            /**
449             * Creates a new service loader for the given service type and class
450             * loader.
451             *
452             * @param  service
453             *         The interface or abstract class representing the service
454             *
455             * @param  loader
456             *         The class loader to be used to load provider-configuration files
457             *         and provider classes, or <tt>null</tt> if the system class
458             *         loader (or, failing that, the bootstrap class loader) is to be
459             *         used
460             * 
461             * @return A new service loader
462             */
463            public static <S> ServiceLoader<S> load(Class<S> service,
464                    ClassLoader loader) {
465                return new ServiceLoader<S>(service, loader);
466            }
467
468            /**
469             * Creates a new service loader for the given service type, using the
470             * current thread's {@linkplain java.lang.Thread#getContextClassLoader
471             * context class loader}.
472             *
473             * <p> An invocation of this convenience method of the form
474             *
475             * <blockquote><pre>
476             * ServiceLoader.load(<i>service</i>)</pre></blockquote>
477             *
478             * is equivalent to
479             *
480             * <blockquote><pre>
481             * ServiceLoader.load(<i>service</i>,
482             *                    Thread.currentThread().getContextClassLoader())</pre></blockquote>
483             *
484             * @param  service
485             *         The interface or abstract class representing the service
486             *
487             * @return A new service loader
488             */
489            public static <S> ServiceLoader<S> load(Class<S> service) {
490                ClassLoader cl = Thread.currentThread().getContextClassLoader();
491                return ServiceLoader.load(service, cl);
492            }
493
494            /**
495             * Creates a new service loader for the given service type, using the
496             * extension class loader.
497             *
498             * <p> This convenience method simply locates the extension class loader,
499             * call it <tt><i>extClassLoader</i></tt>, and then returns
500             *
501             * <blockquote><pre>
502             * ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote>
503             *
504             * <p> If the extension class loader cannot be found then the system class
505             * loader is used; if there is no system class loader then the bootstrap
506             * class loader is used.
507             *
508             * <p> This method is intended for use when only installed providers are
509             * desired.  The resulting service will only find and load providers that
510             * have been installed into the current Java virtual machine; providers on
511             * the application's class path will be ignored.
512             *
513             * @param  service
514             *         The interface or abstract class representing the service
515             *
516             * @return A new service loader
517             */
518            public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
519                ClassLoader cl = ClassLoader.getSystemClassLoader();
520                ClassLoader prev = null;
521                while (cl != null) {
522                    prev = cl;
523                    cl = cl.getParent();
524                }
525                return ServiceLoader.load(service, prev);
526            }
527
528            /**
529             * Returns a string describing this service.
530             *
531             * @return  A descriptive string
532             */
533            public String toString() {
534                return "java.util.ServiceLoader[" + service.getName() + "]";
535            }
536
537        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.