001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.discovery.resource.names;
018
019 import java.io.BufferedReader;
020 import java.io.IOException;
021 import java.io.InputStream;
022 import java.io.InputStreamReader;
023 import java.util.Vector;
024
025 import org.apache.commons.discovery.Resource;
026 import org.apache.commons.discovery.ResourceDiscover;
027 import org.apache.commons.discovery.ResourceIterator;
028 import org.apache.commons.discovery.ResourceNameDiscover;
029 import org.apache.commons.discovery.ResourceNameIterator;
030 import org.apache.commons.discovery.log.DiscoveryLogFactory;
031 import org.apache.commons.discovery.resource.ClassLoaders;
032 import org.apache.commons.discovery.resource.DiscoverResources;
033 import org.apache.commons.logging.Log;
034
035
036
037 /**
038 * Discover ALL files of a given name, and return resource names
039 * contained within the set of files:
040 * <ul>
041 * <li>one resource name per line,</li>
042 * <li>whitespace ignored,</li>
043 * <li>comments begin with '#'</li>
044 * </ul>
045 *
046 * Default discoverer is DiscoverClassLoaderResources,
047 * but it can be set to any other.
048 *
049 * @author Richard A. Sitze
050 * @author Costin Manolache
051 * @author James Strachan
052 */
053 public class DiscoverNamesInFile
054 extends ResourceNameDiscoverImpl
055 implements ResourceNameDiscover
056 {
057 private static Log log = DiscoveryLogFactory.newLog(DiscoverNamesInFile.class);
058 public static void setLog(Log _log) {
059 log = _log;
060 }
061
062 private ResourceDiscover _discoverResources;
063
064 private final String _prefix;
065 private final String _suffix;
066
067 /**
068 * Construct a new resource discoverer
069 */
070 public DiscoverNamesInFile() {
071 _discoverResources = new DiscoverResources();
072 _prefix = null;
073 _suffix = null;
074 }
075
076 /**
077 * Construct a new resource discoverer
078 */
079 public DiscoverNamesInFile(String prefix, String suffix) {
080 _discoverResources = new DiscoverResources();
081 _prefix = prefix;
082 _suffix = suffix;
083 }
084
085 /**
086 * Construct a new resource discoverer
087 */
088 public DiscoverNamesInFile(ClassLoaders loaders) {
089 _discoverResources = new DiscoverResources(loaders);
090 _prefix = null;
091 _suffix = null;
092 }
093
094 /**
095 * Construct a new resource discoverer
096 */
097 public DiscoverNamesInFile(ClassLoaders loaders, String prefix, String suffix) {
098 _discoverResources = new DiscoverResources(loaders);
099 _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 }