View Javadoc

1   package org.apache.onami.spi.core;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static java.nio.charset.Charset.forName;
23  
24  import java.io.BufferedReader;
25  import java.io.Closeable;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.io.InputStreamReader;
29  import java.net.URL;
30  import java.nio.charset.Charset;
31  import java.util.ArrayList;
32  import java.util.Enumeration;
33  import java.util.Iterator;
34  import java.util.List;
35  
36  /**
37   * @param <S> The type of the service to be loaded by this loader.
38   */
39  final class URLServiceNamesIterator<S>
40      extends AbstractServiceClassIterator<S>
41  {
42  
43      /**
44       * The default <code>UTF-8</code> character encoding.
45       */
46      private static final Charset UTF_8 = forName( "UTF-8" );
47  
48      /**
49       * The SPI files to be loaded.
50       */
51      private final Enumeration<URL> serviceResources;
52  
53      /**
54       * @param service the class or interface representing the service being loaded.
55       * @param classLoader the class loader used to locate, load, and instantiate providers.
56       * @param serviceResources
57       * @param providerTypes cached providers types, in instantiation order.
58       */
59      public URLServiceNamesIterator( Class<S> service, ClassLoader classLoader, Enumeration<URL> serviceResources )
60      {
61          super( service, classLoader );
62          this.serviceResources = serviceResources;
63      }
64  
65      /**
66       * {@inheritDoc}
67       */
68      @Override
69      protected boolean hasMorePendingNames()
70      {
71          return serviceResources.hasMoreElements();
72      }
73  
74      /**
75       * {@inheritDoc}
76       */
77      @Override
78      protected Iterator<String> getPendingNames()
79      {
80          return parseServiceFile( serviceResources.nextElement() );
81      }
82  
83      /**
84       * Parse the content of the given URL as a provider-configuration file.
85       *
86       * Method taken from Apache Commons-Digester.
87       *
88       * @param url the URL naming the configuration file to be parsed.
89       * @return a (possibly empty) iterator that will yield the provider-class names in the given configuration file that
90       *         are not yet members of the returned set
91       */
92      private Iterator<String> parseServiceFile( URL url )
93      {
94          final List<String> results = new ArrayList<String>();
95  
96          try
97          {
98              final InputStream input = url.openStream();
99              try
100             {
101                 final BufferedReader reader = new BufferedReader( new InputStreamReader( input, UTF_8 ) );
102 
103                 try
104                 {
105                     String serviceImplName;
106                     while ( ( serviceImplName = reader.readLine() ) != null )
107                     {
108                         int idx = serviceImplName.indexOf( '#' );
109                         if ( idx >= 0 )
110                         {
111                             serviceImplName = serviceImplName.substring( 0, idx );
112                         }
113                         serviceImplName = serviceImplName.trim();
114 
115                         if ( serviceImplName.length() != 0 )
116                         {
117                             results.add( serviceImplName );
118                         }
119                     }
120                 }
121                 finally
122                 {
123                     closeQuietly( reader );
124                 }
125             }
126             finally
127             {
128                 closeQuietly( input );
129             }
130         }
131         catch ( IOException e )
132         {
133             // ignore
134         }
135 
136         return results.iterator();
137     }
138 
139     /**
140      * Unconditionally close a {@link Closeable} element.
141      *
142      * @param closeable the {@link Closeable} element.
143      */
144     private static void closeQuietly( Closeable closeable )
145     {
146         if ( closeable != null )
147         {
148             try
149             {
150                 closeable.close();
151             }
152             catch ( IOException e )
153             {
154                 // close quietly
155             }
156         }
157     }
158 
159 }