View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.discovery.resource.names;
18  
19  import java.io.BufferedReader;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.InputStreamReader;
23  import java.util.Vector;
24  
25  import org.apache.commons.discovery.Resource;
26  import org.apache.commons.discovery.ResourceDiscover;
27  import org.apache.commons.discovery.ResourceIterator;
28  import org.apache.commons.discovery.ResourceNameDiscover;
29  import org.apache.commons.discovery.ResourceNameIterator;
30  import org.apache.commons.discovery.log.DiscoveryLogFactory;
31  import org.apache.commons.discovery.resource.ClassLoaders;
32  import org.apache.commons.discovery.resource.DiscoverResources;
33  import org.apache.commons.logging.Log;
34  
35  
36  
37  /***
38   * Discover ALL files of a given name, and return resource names
39   * contained within the set of files:
40   * <ul>
41   *   <li>one resource name per line,</li>
42   *   <li>whitespace ignored,</li>
43   *   <li>comments begin with '#'</li>
44   * </ul>
45   * 
46   * Default discoverer is DiscoverClassLoaderResources,
47   * but it can be set to any other.
48   *
49   * @author Richard A. Sitze
50   * @author Costin Manolache
51   * @author James Strachan
52   */
53  public class DiscoverNamesInFile
54      extends ResourceNameDiscoverImpl
55      implements ResourceNameDiscover
56  {
57      private static Log log = DiscoveryLogFactory.newLog(DiscoverNamesInFile.class);
58      public static void setLog(Log _log) {
59          log = _log;
60      }
61      
62      private ResourceDiscover _discoverResources;
63      
64      private final String _prefix;
65      private final String _suffix;
66          
67      /***
68       *  Construct a new resource discoverer
69       */
70      public DiscoverNamesInFile() {
71          _discoverResources = new DiscoverResources();
72          _prefix = null;
73          _suffix = null;
74      }
75          
76      /***
77       *  Construct a new resource discoverer
78       */
79      public DiscoverNamesInFile(String prefix, String suffix) {
80          _discoverResources = new DiscoverResources();
81          _prefix = prefix;
82          _suffix = suffix;
83      }
84      
85      /***
86       *  Construct a new resource discoverer
87       */
88      public DiscoverNamesInFile(ClassLoaders loaders) {
89          _discoverResources = new DiscoverResources(loaders);
90          _prefix = null;
91          _suffix = null;
92      }
93      
94      /***
95       *  Construct a new resource discoverer
96       */
97      public DiscoverNamesInFile(ClassLoaders loaders, String prefix, String suffix) {
98          _discoverResources = new DiscoverResources(loaders);
99          _prefix = prefix;
100         _suffix = suffix;
101     }
102     
103     /***
104      *  Construct a new resource discoverer
105      */
106     public DiscoverNamesInFile(ResourceDiscover discoverer) {
107         _discoverResources = discoverer;
108         _prefix = null;
109         _suffix = null;
110     }
111     
112     /***
113      *  Construct a new resource discoverer
114      */
115     public DiscoverNamesInFile(ResourceDiscover discoverer, String prefix, String suffix) {
116         _discoverResources = discoverer;
117         _prefix = prefix;
118         _suffix = suffix;
119     }
120 
121     /***
122      * Specify set of class loaders to be used in searching.
123      */
124     public void setDiscoverer(ResourceDiscover discover) {
125         _discoverResources = discover;
126     }
127 
128     /***
129      * To be used by downstream elements..
130      */
131     public ResourceDiscover getDiscover() {
132         return _discoverResources;
133     }
134 
135     /***
136      * @return Enumeration of ServiceInfo
137      */
138     public ResourceNameIterator findResourceNames(final String serviceName) {
139         String fileName;
140         if (_prefix != null && _prefix.length() > 0) {
141             fileName = _prefix + serviceName;
142         } else {
143             fileName = serviceName;
144         }
145 
146         if (_suffix != null && _suffix.length() > 0) {
147             fileName = fileName + _suffix;
148         }
149 
150         if (log.isDebugEnabled()) {
151             if (_prefix != null  &&  _suffix != null) {
152                 log.debug("find: serviceName='" + serviceName + "' as '" + fileName + "'");
153             } else {
154                 log.debug("find: serviceName = '" + fileName + "'");
155             }
156         }
157 
158 
159         final ResourceIterator files =
160             getDiscover().findResources(fileName);
161 
162         return new ResourceNameIterator() {
163             private int idx = 0;
164             private Vector classNames = null;
165             private String resource = null;
166             
167             public boolean hasNext() {
168                 if (resource == null) {
169                     resource = getNextClassName();
170                 }
171                 return resource != null;
172             }
173             
174             public String nextResourceName() {
175                 String element = resource;
176                 resource = null;
177                 return element;
178             }
179             
180             private String getNextClassName() {
181                 if (classNames == null || idx >= classNames.size()) {
182                     classNames = getNextClassNames();
183                     idx = 0;
184                     if (classNames == null) {
185                         return null;
186                     }
187                 }
188 
189                 String className = (String)classNames.get(idx++);
190 
191                 if (log.isDebugEnabled())
192                     log.debug("getNextClassResource: next class='" + className + "'");
193 
194                 return className;
195             }
196 
197             private Vector getNextClassNames() {
198                 while (files.hasNext()) {
199                     Vector results = readServices(files.nextResource());
200                     if (results != null  &&  results.size() > 0) {
201                         return results;
202                     }
203                 }
204                 return null;
205             }
206         };
207     }
208 
209     /***
210      * Read everything, no defering here..
211      * Ensure that files are closed before we leave.
212      */
213     private Vector readServices(final Resource info) {
214         Vector results = new Vector();
215         
216         InputStream is = info.getResourceAsStream();
217         
218         if( is != null ) {
219             try {
220                 try {
221                     // This code is needed by EBCDIC and other
222                     // strange systems.  It's a fix for bugs
223                     // reported in xerces
224                     BufferedReader rd;
225                     try {
226                         rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
227                     } catch (java.io.UnsupportedEncodingException e) {
228                         rd = new BufferedReader(new InputStreamReader(is));
229                     }
230                     
231                     try {
232                         String serviceImplName;
233                         while( (serviceImplName = rd.readLine()) != null) {
234                             int idx = serviceImplName.indexOf('#');
235                             if (idx >= 0) {
236                                 serviceImplName = serviceImplName.substring(0, idx);
237                             }
238                             serviceImplName = serviceImplName.trim();
239     
240                             if (serviceImplName.length() != 0) {
241                                 results.add(serviceImplName);
242                             }
243                         }
244                     } finally {
245                         rd.close();
246                     }
247                 } finally {
248                     is.close();
249                 }
250             } catch (IOException e) {
251                 // ignore
252             }
253         }
254         
255         return results;
256     }
257 }