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 */
017package org.apache.commons.discovery.resource;
018
019import org.apache.commons.discovery.Resource;
020import org.apache.commons.discovery.ResourceDiscover;
021import org.apache.commons.discovery.ResourceIterator;
022import org.apache.commons.discovery.ResourceNameIterator;
023import org.apache.commons.discovery.resource.names.ResourceNameDiscoverImpl;
024
025/**
026 * Helper class for methods implementing the ResourceDiscover interface.
027 */
028public 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}