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 }