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.classes; 018 019 import java.net.URL; 020 import java.security.CodeSource; 021 import java.util.HashSet; 022 import java.util.Set; 023 024 import org.apache.commons.discovery.ResourceClass; 025 import org.apache.commons.discovery.ResourceClassDiscover; 026 import org.apache.commons.discovery.ResourceClassIterator; 027 import org.apache.commons.discovery.resource.ClassLoaders; 028 import org.apache.commons.logging.Log; 029 import org.apache.commons.logging.LogFactory; 030 031 /** 032 * The findResources() method will check every loader. 033 * 034 * @param <T> The SPI type 035 */ 036 public class DiscoverClasses<T> extends ResourceClassDiscoverImpl<T> implements ResourceClassDiscover<T> { 037 038 private static Log log = LogFactory.getLog(DiscoverClasses.class); 039 040 /** 041 * Sets the {@code Log} for this class. 042 * 043 * @param _log This class {@code Log} 044 * @deprecated This method is not thread-safe 045 */ 046 @Deprecated 047 public static void setLog(Log _log) { 048 log = _log; 049 } 050 051 /** 052 * Construct a new resource discoverer 053 */ 054 public DiscoverClasses() { 055 super(); 056 } 057 058 /** 059 * Construct a new resource discoverer. 060 * 061 * @param classLoaders The class loaders holder 062 */ 063 public DiscoverClasses(ClassLoaders classLoaders) { 064 super(classLoaders); 065 } 066 067 /** 068 * {@inheritDoc} 069 */ 070 @Override 071 public ResourceClassIterator<T> findResourceClasses(final String className) { 072 final String resourceName = className.replace('.','/') + ".class"; 073 074 if (log.isDebugEnabled()) { 075 log.debug("find: className='" + className + "'"); 076 } 077 078 return new ResourceClassIterator<T>() { 079 080 private final Set<URL> history = new HashSet<URL>(); 081 082 private int idx = 0; 083 084 private ResourceClass<T> resource = null; 085 086 public boolean hasNext() { 087 if (resource == null) { 088 resource = getNextClass(); 089 } 090 return resource != null; 091 } 092 093 @Override 094 public ResourceClass<T> nextResourceClass() { 095 ResourceClass<T> element = resource; 096 resource = null; 097 return element; 098 } 099 100 private ResourceClass<T> getNextClass() { 101 while (idx < getClassLoaders().size()) { 102 ClassLoader loader = getClassLoaders().get(idx++); 103 104 URL url = null; 105 106 try { 107 url = loader.getResource(resourceName); 108 } catch (UnsupportedOperationException e) { 109 // ignore 110 } 111 112 if (url == null) { 113 try { 114 CodeSource codeSource = loader.loadClass(className) 115 .getProtectionDomain() 116 .getCodeSource(); 117 if (codeSource != null) { 118 url = new URL(codeSource.getLocation(), resourceName); 119 } 120 // else keep url null 121 } catch (Exception le) { 122 // keep url null 123 } 124 } 125 126 if (url != null) { 127 if (history.add(url)) { 128 if (log.isDebugEnabled()) { 129 log.debug("getNextClass: next URL='" + url + "'"); 130 } 131 132 return new ResourceClass<T>(className, url, loader); 133 } 134 if (log.isDebugEnabled()) { 135 log.debug("getNextClass: duplicate URL='" + url + "'"); 136 } 137 } else { 138 if (log.isDebugEnabled()) { 139 log.debug("getNextClass: loader " + loader + ": '" + resourceName + "' not found"); 140 } 141 } 142 } 143 return null; 144 } 145 }; 146 } 147 148 }