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 }