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