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;
018    
019    import org.apache.commons.discovery.Resource;
020    import org.apache.commons.discovery.ResourceDiscover;
021    import org.apache.commons.discovery.ResourceIterator;
022    import org.apache.commons.discovery.ResourceNameIterator;
023    import org.apache.commons.discovery.resource.names.ResourceNameDiscoverImpl;
024    
025    /**
026     * Helper class for methods implementing the ResourceDiscover interface.
027     */
028    public abstract class ResourceDiscoverImpl extends ResourceNameDiscoverImpl implements ResourceDiscover {
029    
030        private ClassLoaders classLoaders;
031    
032        /**
033         * Construct a new resource discoverer.
034         */
035        public ResourceDiscoverImpl() {
036        }
037    
038        /**
039         * Construct a new resource discoverer.
040         *
041         * @param classLoaders The class laoders holder
042         */
043        public ResourceDiscoverImpl(ClassLoaders classLoaders) {
044            setClassLoaders(classLoaders);
045        }
046    
047        /**
048         * Specify set of class loaders to be used in searching.
049         *
050         * @param loaders The class laoders holder
051         */
052        public void setClassLoaders(ClassLoaders loaders) {
053            classLoaders = loaders;
054        }
055    
056        /**
057         * Specify a new class loader to be used in searching.
058         *
059         * The order of loaders determines the order of the result.
060         * It is recommended to add the most specific loaders first.
061         *
062         * @param loader The new class loader to be added
063         */
064        public void addClassLoader(ClassLoader loader) {
065            getClassLoaders().put(loader);
066        }
067    
068        /**
069         * Returns the class loaders holder.
070         *
071         * @return The class loaders holder
072         */
073        protected ClassLoaders getClassLoaders() {
074            if (classLoaders == null) {
075                classLoaders = ClassLoaders.getLibLoaders(this.getClass(), null, true);
076            }
077            return classLoaders;
078        }
079    
080        /**
081         * {@inheritDoc}
082         */
083        @Override
084        public ResourceNameIterator findResourceNames(String resourceName) {
085            return findResources(resourceName);
086        }
087    
088        /**
089         * {@inheritDoc}
090         */
091        @Override
092        public ResourceNameIterator findResourceNames(ResourceNameIterator resourceNames) {
093            return findResources(resourceNames);
094        }
095    
096        /**
097         * Locate resources that are bound to {@code resourceName}.
098         *
099         * @param resourceName The resource name has to be located
100         * @return The located resources iterator
101         */
102        public abstract ResourceIterator findResources(String resourceName);
103    
104        /**
105         * Locate resources that are bound to <code>resourceNames</code>.
106         *
107         * @param inputNames The resources name iterator has to be located
108         * @return The located resources iterator
109         */
110        public ResourceIterator findResources(final ResourceNameIterator inputNames) {
111            return new ResourceIterator() {
112    
113                private ResourceIterator resources = null;
114    
115                private Resource resource = null;
116    
117                public boolean hasNext() {
118                    if (resource == null) {
119                        resource = getNextResource();
120                    }
121                    return resource != null;
122                }
123    
124                @Override
125                public Resource nextResource() {
126                    Resource rsrc = resource;
127                    resource = null;
128                    return rsrc;
129                }
130    
131                private Resource getNextResource() {
132                    while (inputNames.hasNext() &&
133                           (resources == null  ||  !resources.hasNext())) {
134                        resources = findResources(inputNames.nextResourceName());
135                    }
136    
137                    return (resources != null  &&  resources.hasNext())
138                           ? resources.nextResource()
139                           : null;
140                }
141            };
142        }
143    
144    }