Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libTools / src / org / gvsig / tools / util / impl / DefaultServiceLoader.java @ 31544

History | View | Annotate | Download (5.91 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
 * MA  02110-1301, USA.
20
 * 
21
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2009 {DiSiD Technologies}  {{Task}}
26
 */
27
package org.gvsig.tools.util.impl;
28

    
29
import java.lang.reflect.Method;
30
import java.util.Iterator;
31
import java.util.LinkedHashSet;
32
import java.util.Set;
33

    
34
import org.gvsig.tools.util.ServiceLoader;
35
import org.slf4j.Logger;
36
import org.slf4j.LoggerFactory;
37

    
38
/**
39
 * Implementation which uses reflection to try to use first the standard JDK
40
 * utilities to load service implementation classes, which are available since
41
 * JDK 1.6. If it fails or the JDK used is < 1.6, the old mechanism based on the
42
 * usage of internal sun classes is used.
43
 * <p>
44
 * To register your implementations classes for a service, use the mechanism
45
 * explained in the Java JAR file specification for the JDK version you are
46
 * using:
47
 * <ul>
48
 * <li><a href=
49
 * "http://java.sun.com/j2se/1.4.2/docs/guide/jar/jar.html#Service%20Provider"
50
 * >JDK 1.4</a></li>
51
 * <li><a href=
52
 * "http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider"
53
 * >JDK 1.5</a></li>
54
 * <li><a href="http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider"
55
 * >JDK 1.6</a></li>
56
 * </ul>
57
 * </p>
58
 * 
59
 * 
60
 * @author <a href="mailto:cordinyana@gvsig.org">C?sar Ordi?ana</a>
61
 */
62
public class DefaultServiceLoader implements ServiceLoader {
63
        private static final Logger LOG = LoggerFactory
64
                        .getLogger(DefaultServiceLoader.class);
65

    
66
        public Set load(Class serviceClass) {
67
                return load(serviceClass, null);
68
        }
69

    
70
        public Set load(Class serviceClass, ClassLoader classLoader) {
71
                try {
72
                        return postJDK16Load(serviceClass, classLoader);
73
                } catch (Exception e) {
74
                        LOG.debug("Could not use the JDK >= 1.6 utility classes "
75
                                        + "to load the {} implementation classes, "
76
                                        + "we may be running on a JDK < 1.6, so I will try "
77
                                        + "to use the JDK < 1.6 sun.misc.Service class",
78
                                        serviceClass);
79
                        LOG.trace("The exception thrown is: ", e);
80
                }
81

    
82
                try {
83
                        return preJDK16Load(serviceClass, classLoader);
84
                } catch (Exception e) {
85
                        LOG
86
                                        .error("Error finding available " + serviceClass
87
                                                        + " objects", e);
88
                }
89
                return null;
90
        }
91

    
92
        /**
93
         * Load the classes using the pre JDK 1.6 sun utilities.
94
         */
95
        private Set preJDK16Load(Class serviceClass, ClassLoader classLoader)
96
                        throws Exception {
97
                LOG.info("Using the sun.misc.Service to load the {} {}", serviceClass,
98
                                serviceClass.isInterface() ? "implementations" : "extensions");
99

    
100
                // Use reflection to call the internal Sun JDK class and avoid
101
                // compiler errors in eclipse
102
                Class serviceClazz = Class.forName("sun.misc.Service");
103

    
104
                if (serviceClazz == null) {
105
                        LOG.error("Could not load Class sun.misc.Service "
106
                                        + "using reflection");
107
                        return null;
108
                }
109

    
110
                Method providersMethod = null;
111

    
112
                if (classLoader == null) {
113
                        providersMethod = serviceClazz.getMethod("providers",
114
                                        new Class[] { Class.class });
115
                } else {
116
                        providersMethod = serviceClazz.getMethod("providers", new Class[] {
117
                                        Class.class, ClassLoader.class });
118
                }
119

    
120
                Iterator iterator = null;
121
                if (classLoader == null) {
122
                        iterator = (Iterator) providersMethod.invoke(null,
123
                                        new Object[] { serviceClass });
124
                } else {
125
                        iterator = (Iterator) providersMethod.invoke(null, new Object[] {
126
                                        serviceClass, classLoader });
127
                }
128
                if (iterator == null) {
129
                        LOG.debug("Empty {} objects iterator returned by the "
130
                                        + "sun.misc.Service.providers method", serviceClass);
131
                        return null;
132
                }
133

    
134
                Set services = new LinkedHashSet();
135
                for (; iterator.hasNext();) {
136
                        services.add(iterator.next());
137
                }
138
                return services;
139
        }
140

    
141
        /**
142
         * Load the classes using the JDK 1.6 standard utilities.
143
         */
144
        private Set postJDK16Load(Class serviceClass, ClassLoader classLoader)
145
                        throws Exception {
146
                LOG.info("Using the java.util.ServiceLoader to load " + "the {} {}",
147
                                serviceClass, serviceClass.isInterface() ? "implementations"
148
                                                : "extensions");
149

    
150
                // Use reflection to call the JDK >= 1.6 utility classes and being
151
                // able to compile with JDK 1.4 or 1.5
152
                Class serviceLoaderClazz = Class.forName("java.util.ServiceLoader");
153
                Method loadMethod = null;
154
                if (classLoader == null) {
155
                        loadMethod = serviceLoaderClazz.getMethod("load",
156
                                        new Class[] { Class.class });
157
                } else {
158
                        loadMethod = serviceLoaderClazz.getMethod("load", new Class[] {
159
                                        Class.class, ClassLoader.class });
160
                }
161

    
162
                Object serviceLoader = null;
163

    
164
                if (classLoader == null) {
165
                        serviceLoader = loadMethod.invoke(null,
166
                                        new Object[] { serviceClass });
167
                } else {
168
                        serviceLoader = loadMethod.invoke(null, new Object[] {
169
                                        serviceClass, classLoader });
170
                }
171
                if (serviceLoader == null) {
172
                        LOG.error("Could not load a ServiceLoader to load {} objects",
173
                                        serviceClass);
174
                        return null;
175
                }
176

    
177
                Method iteratorMethod = serviceLoaderClazz.getMethod("iterator", null);
178
                Iterator iterator = (Iterator) iteratorMethod.invoke(serviceLoader,
179
                                null);
180
                if (iterator == null) {
181
                        LOG.debug(
182
                                        "java.util.ServiceLoader of {} returned an empty iterator",
183
                                        serviceClass);
184
                        return null;
185
                }
186

    
187
                Set services = new LinkedHashSet();
188
                for (; iterator.hasNext();) {
189
                        services.add(iterator.next());
190
                }
191
                return services;
192
        }
193

    
194
}