View Javadoc

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.Map;
33  import java.util.ServiceLoader;
34  import java.util.Set;
35  import javax.faces.context.ExternalContext;
36  
37  import org.apache.myfaces.shared.util.ClassUtils;
38  import org.apache.myfaces.spi.ServiceProviderFinder;
39  
40  /**
41   * 
42   * @author Leonardo Uribe
43   * @since 2.0.3
44   *
45   */
46  public class DefaultServiceProviderFinder extends ServiceProviderFinder
47  {
48      private static final String META_INF_SERVICES = "META-INF/services/";
49      
50      private Map<String, List<String>> knownServicesMap = null;
51  
52      protected Set<URL> getURLs(String spiClass)
53      {
54          // Use LinkedHashSet to preserve iteration order
55          Enumeration<URL> profiles = null;
56          try
57          {
58              profiles = ClassUtils.getContextClassLoader().getResources(
59                      META_INF_SERVICES + spiClass);
60          }
61          catch (IOException e)
62          {
63              return null;
64          }
65          if (null != profiles && profiles.hasMoreElements())
66          {
67              Set<URL> urls = new LinkedHashSet<URL>();
68              while (profiles.hasMoreElements())
69              {
70                  URL url = profiles.nextElement();
71                  urls.add(url);
72              }
73              return urls;
74          }
75          return Collections.emptySet();
76      }
77  
78      @Override
79      public List<String> getServiceProviderList(String spiClass)
80      {
81          if (knownServicesMap != null)
82          {
83              List<String> result = knownServicesMap.get(spiClass);
84              if (result != null)
85              {
86                  return result;
87              }
88          }
89          
90          Set<URL> urls = getURLs(spiClass);
91  
92          if (!urls.isEmpty())
93          {
94              List<String> results = new LinkedList<String>();
95              for (URL url : urls)
96              {
97                  InputStream is = null;
98      
99                  try
100                 {
101                     try
102                     {
103                         is = openStreamWithoutCache(url);
104                         if (is != null)
105                         {
106                             // This code is needed by EBCDIC and other
107                             // strange systems.  It's a fix for bugs
108                             // reported in xerces
109                             BufferedReader rd;
110                             try
111                             {
112                                 rd = new BufferedReader(new InputStreamReader(is,
113                                         "UTF-8"));
114                             }
115                             catch (java.io.UnsupportedEncodingException e)
116                             {
117                                 rd = new BufferedReader(new InputStreamReader(is));
118                             }
119     
120                             try
121                             {
122                                 String serviceImplName;
123                                 while ((serviceImplName = rd.readLine()) != null)
124                                 {
125                                     int idx = serviceImplName.indexOf('#');
126                                     if (idx >= 0)
127                                     {
128                                         serviceImplName = serviceImplName
129                                                 .substring(0, idx);
130                                     }
131                                     serviceImplName = serviceImplName.trim();
132     
133                                     if (serviceImplName.length() != 0)
134                                     {
135                                         results.add(serviceImplName);
136                                     }
137                                 }
138                             }
139                             finally
140                             {
141                                 if (rd != null)
142                                 {
143                                     rd.close();
144                                 }
145                             }
146                         }
147                     }
148                     finally
149                     {
150                         if (is != null)
151                         {
152                             is.close();
153                         }
154                     }
155                 }
156                 catch (IOException e)
157                 {
158                     // ignore
159                 }
160             }
161             return results;
162         }
163         return Collections.emptyList();
164     }
165 
166     private InputStream openStreamWithoutCache(URL url) throws IOException
167     {
168         URLConnection connection = url.openConnection();
169         connection.setUseCaches(false);
170         return connection.getInputStream();
171     }
172     
173     @Override
174     public <S> ServiceLoader<S> load(Class<S> spiClass)
175     {
176         return ServiceLoader.load(spiClass);
177     }
178 
179     @Override
180     public void initKnownServiceProviderMapInfo(ExternalContext ectx, Map<String, List<String>> map)
181     {
182         knownServicesMap = map;
183     }
184 }