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 }