001 /*
002 * Copyright 2005,2009 Ivan SZKIBA
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.ini4j.spi;
017
018 import java.io.BufferedReader;
019 import java.io.InputStream;
020 import java.io.InputStreamReader;
021
022 /**
023 * JDK JAR Services API alap??? service keres??? oszt???ly.
024 *
025 * @author Szkiba Iv???n
026 * @version $Name: $
027 */
028 public final class ServiceFinder
029 {
030 private static final String SERVICES_PATH = "META-INF/services/";
031
032 private ServiceFinder()
033 {
034 }
035
036 /**
037 * Service objektum keres???s ???s p???ld???nyos???t???s
038 *
039 * a JDK JAR specifik???ci???ban defini???lt <B>Services API</B>-nak
040 * megfelel???en service oszt???ly keres???s, majd pedig p???ld???ny k???pz???s a context
041 * ClassLoader seg???ts???g???vel.</p><p>
042 * Az implement???l??? oszt???ly n???v keres???se a <CODE>serviceId</CODE> nev???
043 * system property vizsg???lat???val kezd???dik. Amennyiben nincs ilyen
044 * property, ???gy a keres???s a
045 * <CODE>/META-INF/services/<I>serviceId</I></CODE> nev??? file tartalm???val
046 * folytat???dik. Amennyiben nincs ilyen nev??? file, ???gy a param???terk???nt ???tadott
047 * <CODE>defaultService</CODE> lesz az oszt???ly neve.</p><p>
048 * A fenti keres???st k???vet???en t???rt???nik a p???ld???ny k???pz???s. A visszat???r???si
049 * ???rt???k mindig egy val???di objektum, l???v???n minden hiba exception-t gener???l.
050 * @param <T> type
051 * @param clazz keresett oszt???ly/service neve
052 * @throws IllegalArgumentException keres???si vagy p???ld???nyos???t???si hiba eset???n
053 * @return a keresett oszt???ly implement???l??? objektum
054 */
055 public static <T> T findService(Class<T> clazz)
056 {
057 try
058 {
059
060 // ez a cast nem lenne sz??ks??ges, de ??gy a ClassCastException csak a h??v??n??l j??n...
061 return clazz.cast(findServiceClass(clazz).newInstance());
062 }
063 catch (Exception x)
064 {
065 throw (IllegalArgumentException) new IllegalArgumentException("Provider " + clazz.getName() + " could not be instantiated: " + x)
066 .initCause(x);
067 }
068 }
069
070 @SuppressWarnings(Warnings.UNCHECKED)
071 static <T> Class<? extends T> findServiceClass(Class<T> clazz) throws IllegalArgumentException
072 {
073 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
074 String serviceClassName = findServiceClassName(clazz.getName());
075 Class<T> ret = clazz;
076
077 if (serviceClassName != null)
078 {
079 try
080 {
081 ret = (Class<T>) ((classLoader == null) ? Class.forName(serviceClassName) : classLoader.loadClass(serviceClassName));
082 }
083 catch (ClassNotFoundException x)
084 {
085 throw (IllegalArgumentException) new IllegalArgumentException("Provider " + serviceClassName + " not found").initCause(x);
086 }
087 }
088
089 return ret;
090 }
091
092 static String findServiceClassName(String serviceId) throws IllegalArgumentException
093 {
094 String serviceClassName = null;
095
096 // Use the system property first
097 try
098 {
099 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 }