001    /**
002     *
003     * Copyright 2005 The Apache Software Foundation
004     *
005     *  Licensed under the Apache License, Version 2.0 (the "License");
006     *  you may not use this file except in compliance with the License.
007     *  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.geronimo.kernel.config;
018    
019    import java.util.List;
020    import java.util.Collection;
021    import java.util.ArrayList;
022    import java.util.Iterator;
023    import java.util.LinkedHashSet;
024    import java.util.Collections;
025    import java.util.Set;
026    import java.io.File;
027    import java.net.MalformedURLException;
028    
029    import org.apache.geronimo.kernel.repository.ArtifactResolver;
030    import org.apache.geronimo.kernel.repository.MissingDependencyException;
031    import org.apache.geronimo.kernel.repository.Dependency;
032    import org.apache.geronimo.kernel.repository.Artifact;
033    import org.apache.geronimo.kernel.repository.Repository;
034    import org.apache.geronimo.kernel.repository.ImportType;
035    
036    /**
037     * @version $Rev: 410741 $ $Date: 2006-05-31 21:35:48 -0700 (Wed, 31 May 2006) $
038     */
039    public class ConfigurationResolver {
040        private final Artifact configurationId;
041        private final ArtifactResolver artifactResolver;
042        private final Collection repositories;
043    
044        /**
045         * file or configstore used to resolve classpath parts
046         */
047        private final File baseDir;
048        private final ConfigurationStore configurationStore;
049    
050        /**
051         * For nested configurations, the module name will be non-null.
052         */
053        private final String moduleName;
054    
055        public ConfigurationResolver(Artifact configurationId, File baseDir) {
056            if (configurationId == null)  throw new NullPointerException("configurationId is null");
057    
058            this.configurationId = configurationId;
059            this.baseDir = baseDir;
060            artifactResolver = null;
061            repositories = Collections.EMPTY_SET;
062            configurationStore = null;
063            moduleName = null;
064        }
065    
066        public ConfigurationResolver(ConfigurationData configurationData, Collection repositories, ArtifactResolver artifactResolver) {
067            if (configurationData == null)  throw new NullPointerException("configurationData is null");
068            if (repositories == null) repositories = Collections.EMPTY_SET;
069    
070            configurationId = configurationData.getId();
071            this.artifactResolver = artifactResolver;
072            this.repositories = repositories;
073            configurationStore = configurationData.getConfigurationStore();
074            if (null != configurationData.getInPlaceConfigurationDir()) {
075                baseDir = configurationData.getInPlaceConfigurationDir();
076            } else {
077                baseDir = configurationData.getConfigurationDir();
078            }
079            moduleName = null;
080        }
081    
082        private ConfigurationResolver(Artifact configurationId, ArtifactResolver artifactResolver, Collection repositories, File baseDir, ConfigurationStore configurationStore, String moduleName) {
083            this.configurationId = configurationId;
084            this.artifactResolver = artifactResolver;
085            this.repositories = repositories;
086            this.baseDir = baseDir;
087            this.configurationStore = configurationStore;
088            this.moduleName = moduleName;
089        }
090    
091        public ConfigurationResolver createChildResolver(String moduleName) {
092            if (moduleName == null) throw new NullPointerException("moduleName is null");
093            if (this.moduleName != null) {
094                moduleName = this.moduleName + '/' + moduleName;
095            }
096    
097            File childBaseDir = null;
098            if (baseDir != null) {
099                childBaseDir = new File(baseDir, moduleName);
100            }
101            return new ConfigurationResolver(configurationId, artifactResolver, repositories, childBaseDir, configurationStore, moduleName);
102        }
103    
104        public File resolve(Artifact artifact) throws MissingDependencyException {
105            for (Iterator j = repositories.iterator(); j.hasNext();) {
106                Repository repository = (Repository) j.next();
107                if (repository.contains(artifact)) {
108                    File file = repository.getLocation(artifact);
109                    return file;
110                }
111            }
112            throw new MissingDependencyException("Unable to resolve dependency " + artifact);
113        }
114    
115        public Set resolve(String pattern) throws MalformedURLException, NoSuchConfigException {
116            if (configurationStore != null) {
117                Set matches = configurationStore.resolve(configurationId, moduleName, pattern);
118                return matches;
119            } else if (baseDir != null) {
120                Set matches = IOUtil.search(baseDir, pattern);
121                return matches;
122            } else {
123                throw new IllegalStateException("No configurationStore or baseDir supplied so paths can not be resolved");
124            }
125        }
126    
127        public List resolveTransitiveDependencies(Collection parents, List dependencies) throws MissingDependencyException {
128            List resolvedDependencies = new ArrayList();
129            for (Iterator iterator = dependencies.iterator(); iterator.hasNext();) {
130                Dependency dependency = resolveDependency(parents, (Dependency) iterator.next());
131    
132                if (!resolvedDependencies.contains(dependency)) {
133                    resolvedDependencies.add(dependency);
134    
135                    List childDependencies = getChildDependencies(dependency);
136                    if (!childDependencies.isEmpty()) {
137                        childDependencies = resolveTransitiveDependencies(parents, childDependencies);
138                        resolvedDependencies.addAll(childDependencies);
139                    }
140                }
141            }
142            return resolvedDependencies;
143        }
144    
145        private Dependency resolveDependency(Collection parents, Dependency dependency) throws MissingDependencyException {
146            Artifact artifact = dependency.getArtifact();
147    
148            // if it is already resolved we are done
149            if (artifact.isResolved()) {
150                return dependency;
151            }
152    
153            // we need an artifact resolver at this point
154            if (artifactResolver == null) {
155                throw new MissingDependencyException("Artifact is not resolved and there no artifact resolver available: " + artifact);
156            }
157    
158            // resolve the artifact
159            artifact = artifactResolver.resolveInClassLoader(artifact, parents);
160    
161            // build a new dependency object to contain the resolved artifact
162            Dependency resolvedDependency = new Dependency(artifact, dependency.getImportType());
163            return resolvedDependency;
164        }
165    
166        private ArrayList getChildDependencies(Dependency dependency) {
167            ArrayList childDependencies = new ArrayList();
168            for (Iterator repositoryIterator = repositories.iterator(); repositoryIterator.hasNext();) {
169                Repository repository = (Repository) repositoryIterator.next();
170                if (repository.contains(dependency.getArtifact())) {
171                    // get the child artifacts
172                    LinkedHashSet childArtifacts = repository.getDependencies(dependency.getArtifact());
173                    for (Iterator artifactIterator = childArtifacts.iterator(); artifactIterator.hasNext();) {
174                        Artifact artifact = (Artifact) artifactIterator.next();
175                        // add each child as a classes-only dependency
176                        childDependencies.add(new Dependency(artifact,  ImportType.CLASSES));
177                    }
178                }
179            }
180            return childDependencies;
181        }
182    }