1 /*
2 * Copyright 2005,2009 Ivan SZKIBA
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.ini4j.spi;
17
18 import java.io.BufferedReader;
19 import java.io.InputStream;
20 import java.io.InputStreamReader;
21
22 /**
23 * JDK JAR Services API alap� service keres� oszt�ly.
24 *
25 * @author Szkiba Iv�n
26 * @version $Name: $
27 */
28 final class ServiceFinder
29 {
30 private static final String SERVICES_PATH = "META-INF/services/";
31
32 private ServiceFinder()
33 {
34 }
35
36 /**
37 * Service objektum keres�s �s p�ld�nyos�t�s
38 *
39 * a JDK JAR specifik�ci�ban defini�lt <B>Services API</B>-nak
40 * megfelel�en service oszt�ly keres�s, majd pedig p�ld�ny k�pz�s a context
41 * ClassLoader seg�ts�g�vel.</p><p>
42 * Az implement�l� oszt�ly n�v keres�se a <CODE>serviceId</CODE> nev�
43 * system property vizsg�lat�val kezd�dik. Amennyiben nincs ilyen
44 * property, �gy a keres�s a
45 * <CODE>/META-INF/services/<I>serviceId</I></CODE> nev� file tartalm�val
46 * folytat�dik. Amennyiben nincs ilyen nev� file, �gy a param�terk�nt �tadott
47 * <CODE>defaultService</CODE> lesz az oszt�ly neve.</p><p>
48 * A fenti keres�st k�vet�en t�rt�nik a p�ld�ny k�pz�s. A visszat�r�si
49 * �rt�k mindig egy val�di objektum, l�v�n minden hiba exception-t gener�l.
50 * @param <T> type
51 * @param clazz keresett oszt�ly/service neve
52 * @throws IllegalArgumentException keres�si vagy p�ld�nyos�t�si hiba eset�n
53 * @return a keresett oszt�ly implement�l� objektum
54 */
55 static <T> T findService(Class<T> clazz)
56 {
57 try
58 {
59
60 // ez a cast nem lenne szükséges, de úgy a ClassCastException csak a hívónál jön...
61 return clazz.cast(findServiceClass(clazz).newInstance());
62 }
63 catch (Exception x)
64 {
65 throw (IllegalArgumentException) new IllegalArgumentException("Provider " + clazz.getName() + " could not be instantiated: " + x)
66 .initCause(x);
67 }
68 }
69
70 @SuppressWarnings(Warnings.UNCHECKED)
71 static <T> Class<? extends T> findServiceClass(Class<T> clazz) throws IllegalArgumentException
72 {
73 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
74 String serviceClassName = findServiceClassName(clazz.getName());
75 Class<T> ret = clazz;
76
77 if (serviceClassName != null)
78 {
79 try
80 {
81 ret = (Class<T>) ((classLoader == null) ? Class.forName(serviceClassName) : classLoader.loadClass(serviceClassName));
82 }
83 catch (ClassNotFoundException x)
84 {
85 throw (IllegalArgumentException) new IllegalArgumentException("Provider " + serviceClassName + " not found").initCause(x);
86 }
87 }
88
89 return ret;
90 }
91
92 static String findServiceClassName(String serviceId) throws IllegalArgumentException
93 {
94 String serviceClassName = null;
95
96 // Use the system property first
97 try
98 {
99 String systemProp = System.getProperty(serviceId);
100
101 if (systemProp != null)
102 {
103 serviceClassName = systemProp;
104 }
105 }
106 catch (SecurityException x)
107 {
108 assert true;
109 }
110
111 if (serviceClassName == null)
112 {
113 serviceClassName = loadLine(SERVICES_PATH + serviceId);
114 }
115
116 return serviceClassName;
117 }
118
119 private static String loadLine(String servicePath)
120 {
121 String ret = null;
122
123 // try to find services in CLASSPATH
124 try
125 {
126 InputStream is = null;
127 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
128
129 if (classLoader == null)
130 {
131 is = ClassLoader.getSystemResourceAsStream(servicePath);
132 }
133 else
134 {
135 is = classLoader.getResourceAsStream(servicePath);
136 }
137
138 if (is != null)
139 {
140 BufferedReader rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
141 String line = rd.readLine();
142
143 rd.close();
144 if (line != null)
145 {
146 line = line.trim();
147 if (line.length() != 0)
148 {
149 ret = line.split("\\s|#")[0];
150 }
151 }
152 }
153 }
154 catch (Exception x)
155 {
156 assert true;
157 }
158
159 return ret;
160 }
161 }