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.classes;
18  
19  import java.net.URL;
20  import java.security.CodeSource;
21  import java.util.HashSet;
22  import java.util.Set;
23  
24  import org.apache.commons.discovery.ResourceClass;
25  import org.apache.commons.discovery.ResourceClassDiscover;
26  import org.apache.commons.discovery.ResourceClassIterator;
27  import org.apache.commons.discovery.resource.ClassLoaders;
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  
31  /**
32   * The findResources() method will check every loader.
33   *
34   * @param <T> The SPI type
35   */
36  public class DiscoverClasses<T> extends ResourceClassDiscoverImpl<T> implements ResourceClassDiscover<T> {
37  
38      private static Log log = LogFactory.getLog(DiscoverClasses.class);
39  
40      /**
41       * Sets the {@code Log} for this class.
42       *
43       * @param _log This class {@code Log}
44       * @deprecated This method is not thread-safe
45       */
46      @Deprecated
47      public static void setLog(Log _log) {
48          log = _log;
49      }
50  
51      /**
52       * Construct a new resource discoverer
53       */
54      public DiscoverClasses() {
55          super();
56      }
57  
58      /**
59       * Construct a new resource discoverer.
60       *
61       * @param classLoaders The class loaders holder
62       */
63      public DiscoverClasses(ClassLoaders classLoaders) {
64          super(classLoaders);
65      }
66  
67      /**
68       * {@inheritDoc}
69       */
70      @Override
71      public ResourceClassIterator<T> findResourceClasses(final String className) {
72          final String resourceName = className.replace('.','/') + ".class";
73  
74          if (log.isDebugEnabled()) {
75              log.debug("find: className='" + className + "'");
76          }
77  
78          return new ResourceClassIterator<T>() {
79  
80              private final Set<URL> history = new HashSet<URL>();
81  
82              private int idx = 0;
83  
84              private ResourceClass<T> resource = null;
85  
86              public boolean hasNext() {
87                  if (resource == null) {
88                      resource = getNextClass();
89                  }
90                  return resource != null;
91              }
92  
93              @Override
94              public ResourceClass<T> nextResourceClass() {
95                  ResourceClass<T> element = resource;
96                  resource = null;
97                  return element;
98              }
99  
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 }