1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.myfaces.spi.impl;
20
21 import java.io.BufferedReader;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.InputStreamReader;
25 import java.net.URL;
26 import java.net.URLConnection;
27 import java.util.Collections;
28 import java.util.Enumeration;
29 import java.util.LinkedHashSet;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Set;
33
34 import org.apache.myfaces.shared.util.ClassUtils;
35 import org.apache.myfaces.spi.ServiceProviderFinder;
36
37 /**
38 *
39 * @author Leonardo Uribe
40 * @since 2.0.3
41 *
42 */
43 public class DefaultServiceProviderFinder extends ServiceProviderFinder
44 {
45 private static final String META_INF_SERVICES = "META-INF/services/";
46
47 protected Set<URL> getURLs(String spiClass)
48 {
49 // Use LinkedHashSet to preserve iteration order
50 Enumeration<URL> profiles = null;
51 try
52 {
53 profiles = ClassUtils.getContextClassLoader().getResources(
54 META_INF_SERVICES + spiClass);
55 }
56 catch (IOException e)
57 {
58 return null;
59 }
60 if (null != profiles && profiles.hasMoreElements())
61 {
62 Set<URL> urls = new LinkedHashSet<URL>();
63 while (profiles.hasMoreElements())
64 {
65 URL url = profiles.nextElement();
66 urls.add(url);
67 }
68 return urls;
69 }
70 return Collections.emptySet();
71 }
72
73 public List<String> getServiceProviderList(String spiClass)
74 {
75 Set<URL> urls = getURLs(spiClass);
76
77 if (!urls.isEmpty())
78 {
79 List<String> results = new LinkedList<String>();
80 for (URL url : urls)
81 {
82 InputStream is = null;
83
84 try
85 {
86 try
87 {
88 is = openStreamWithoutCache(url);
89 if (is != null)
90 {
91 // This code is needed by EBCDIC and other
92 // strange systems. It's a fix for bugs
93 // reported in xerces
94 BufferedReader rd;
95 try
96 {
97 rd = new BufferedReader(new InputStreamReader(is,
98 "UTF-8"));
99 }
100 catch (java.io.UnsupportedEncodingException e)
101 {
102 rd = new BufferedReader(new InputStreamReader(is));
103 }
104
105 try
106 {
107 String serviceImplName;
108 while ((serviceImplName = rd.readLine()) != null)
109 {
110 int idx = serviceImplName.indexOf('#');
111 if (idx >= 0)
112 {
113 serviceImplName = serviceImplName
114 .substring(0, idx);
115 }
116 serviceImplName = serviceImplName.trim();
117
118 if (serviceImplName.length() != 0)
119 {
120 results.add(serviceImplName);
121 }
122 }
123 }
124 finally
125 {
126 if (rd != null)
127 {
128 rd.close();
129 }
130 }
131 }
132 }
133 finally
134 {
135 if (is != null)
136 {
137 is.close();
138 }
139 }
140 }
141 catch (IOException e)
142 {
143 // ignore
144 }
145 }
146 return results;
147 }
148 return Collections.emptyList();
149 }
150
151 private InputStream openStreamWithoutCache(URL url) throws IOException
152 {
153 URLConnection connection = url.openConnection();
154 connection.setUseCaches(false);
155 return connection.getInputStream();
156 }
157 }