001
014
015 package com.liferay.portal.kernel.util;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019
020 import java.io.BufferedReader;
021 import java.io.InputStream;
022 import java.io.InputStreamReader;
023
024 import java.lang.reflect.Constructor;
025
026 import java.net.MalformedURLException;
027 import java.net.URL;
028
029 import java.util.ArrayList;
030 import java.util.Enumeration;
031 import java.util.List;
032
033
038 public class ServiceLoader {
039
040 public static <S> List<S> load(Class<S> clazz) throws Exception {
041 return load(clazz, _serviceLoaderCondition);
042 }
043
044 public static <S> List<S> load(
045 Class<S> clazz, ServiceLoaderCondition serviceLoaderCondition)
046 throws Exception {
047
048 Thread currentThread = Thread.currentThread();
049
050 ClassLoader classLoader = currentThread.getContextClassLoader();
051
052 return load(classLoader, clazz, serviceLoaderCondition);
053 }
054
055 public static <S> List<S> load(ClassLoader classLoader, Class<S> clazz)
056 throws Exception {
057
058 return load(classLoader, clazz, _serviceLoaderCondition);
059 }
060
061 public static <S> List<S> load(
062 ClassLoader classLoader, Class<S> clazz,
063 ServiceLoaderCondition serviceLoaderCondition)
064 throws Exception {
065
066 Enumeration<URL> enu = classLoader.getResources(
067 "META-INF/services/" + clazz.getName());
068
069 List<S> services = new ArrayList<>();
070
071 while (enu.hasMoreElements()) {
072 URL url = enu.nextElement();
073
074 if (!serviceLoaderCondition.isLoad(url)) {
075 continue;
076 }
077
078 try {
079 _load(services, classLoader, clazz, url);
080 }
081 catch (Exception e) {
082 _log.error(
083 "Unable to load " + clazz + " with " + classLoader, e);
084 }
085 }
086
087 return services;
088 }
089
090
094 public static URL normalizeURL(URL url) throws MalformedURLException {
095 String urlString = url.toString();
096
097 if (urlString.startsWith("vfsfile:")) {
098 urlString = StringUtil.replaceFirst(urlString, "vfsfile:", "file:");
099 }
100 else if (urlString.startsWith("vfsjar:")) {
101 urlString = StringUtil.replaceFirst(urlString, "vfsjar:", "file:");
102 }
103 else if (urlString.startsWith("vfszip:")) {
104 urlString = StringUtil.replaceFirst(urlString, "vfszip:", "file:");
105 }
106
107 if (urlString.contains(".jar/")) {
108 urlString = StringUtil.replaceFirst(urlString, ".jar/", ".jar!/");
109
110 if (urlString.startsWith("file:")) {
111 urlString = "jar:" + urlString;
112 }
113 }
114
115 urlString = urlString.replace('\\', '/');
116
117 int index = urlString.indexOf("file:");
118
119 if (index != -1) {
120 index += 5;
121
122 if (urlString.charAt(index) != '/') {
123 urlString =
124 urlString.substring(0, index) + '/' +
125 urlString.substring(index);
126 }
127 }
128
129 return new URL(urlString);
130 }
131
132 private static <S> void _load(
133 List<S> services, ClassLoader classLoader, Class<S> clazz, URL url)
134 throws Exception {
135
136 if (ServerDetector.isJBoss5()) {
137 url = normalizeURL(url);
138 }
139
140 try (InputStream inputStream = url.openStream()) {
141 BufferedReader bufferedReader = new BufferedReader(
142 new InputStreamReader(inputStream, StringPool.UTF8));
143
144 while (true) {
145 String line = bufferedReader.readLine();
146
147 if (line == null) {
148 break;
149 }
150
151 int comment = line.indexOf(CharPool.POUND);
152
153 if (comment >= 0) {
154 line = line.substring(0, comment);
155 }
156
157 String name = line.trim();
158
159 if (name.length() == 0) {
160 continue;
161 }
162
163 Class<?> serviceClass = Class.forName(name, true, classLoader);
164
165 Class<? extends S> serviceImplClass = serviceClass.asSubclass(
166 clazz);
167
168 Constructor<? extends S> constructor =
169 serviceImplClass.getConstructor();
170
171 S service = constructor.newInstance();
172
173 services.add(service);
174 }
175 }
176 }
177
178 private static final Log _log = LogFactoryUtil.getLog(ServiceLoader.class);
179
180 private static final ServiceLoaderCondition _serviceLoaderCondition =
181 new DefaultServiceLoaderCondition();
182
183 }