001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.geronimo.kernel.repository; 019 020 import java.util.Collection; 021 import java.util.Collections; 022 import java.util.Iterator; 023 import java.util.LinkedHashSet; 024 import java.util.SortedSet; 025 import java.util.TreeSet; 026 import java.util.Map; 027 028 import org.apache.geronimo.gbean.GBeanInfo; 029 import org.apache.geronimo.gbean.GBeanInfoBuilder; 030 import org.apache.geronimo.kernel.config.Configuration; 031 032 /** 033 * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $ 034 */ 035 public class DefaultArtifactResolver implements ArtifactResolver { 036 private final ArtifactManager artifactManager; 037 private final Collection repositories; 038 private final Map explicitResolution; 039 040 public DefaultArtifactResolver(ArtifactManager artifactManager, ListableRepository repository) { 041 this.artifactManager = artifactManager; 042 this.repositories = Collections.singleton(repository); 043 this.explicitResolution = Collections.EMPTY_MAP; 044 } 045 046 public DefaultArtifactResolver(ArtifactManager artifactManager, Collection repositories, Map explicitResolution) { 047 this.artifactManager = artifactManager; 048 this.repositories = repositories; 049 this.explicitResolution = explicitResolution == null? Collections.EMPTY_MAP: explicitResolution; 050 } 051 052 053 public Artifact generateArtifact(Artifact source, String defaultType) { 054 if(source.isResolved()) { 055 Artifact deAliased = (Artifact) explicitResolution.get(source); 056 if (deAliased != null) { 057 return deAliased; 058 } 059 return source; 060 } 061 String groupId = source.getGroupId() == null ? Artifact.DEFAULT_GROUP_ID : source.getGroupId(); 062 String artifactId = source.getArtifactId(); 063 String type = source.getType() == null ? defaultType : source.getType(); 064 Version version = source.getVersion() == null ? new Version(Long.toString(System.currentTimeMillis())) : source.getVersion(); 065 066 return new Artifact(groupId, artifactId, version, type); 067 } 068 069 public Artifact queryArtifact(Artifact artifact) throws MultipleMatchesException { 070 Artifact[] all = queryArtifacts(artifact); 071 if(all.length > 1) { 072 throw new MultipleMatchesException(artifact); 073 } 074 return all.length == 0 ? null : all[0]; 075 } 076 077 public Artifact[] queryArtifacts(Artifact artifact) { 078 LinkedHashSet set = new LinkedHashSet(); 079 for (Iterator iterator = repositories.iterator(); iterator.hasNext();) { 080 ListableRepository repository = (ListableRepository) iterator.next(); 081 set.addAll(repository.list(artifact)); 082 } 083 return (Artifact[]) set.toArray(new Artifact[set.size()]); 084 } 085 086 public LinkedHashSet resolveInClassLoader(Collection artifacts) throws MissingDependencyException { 087 return resolveInClassLoader(artifacts, Collections.EMPTY_SET); 088 } 089 090 public LinkedHashSet resolveInClassLoader(Collection artifacts, Collection parentConfigurations) throws MissingDependencyException { 091 LinkedHashSet resolvedArtifacts = new LinkedHashSet(); 092 for (Iterator iterator = artifacts.iterator(); iterator.hasNext();) { 093 Artifact artifact = (Artifact) iterator.next(); 094 if (!artifact.isResolved()) { 095 artifact = resolveInClassLoader(artifact, parentConfigurations); 096 } 097 resolvedArtifacts.add(artifact); 098 } 099 return resolvedArtifacts; 100 } 101 102 public Artifact resolveInClassLoader(Artifact source) throws MissingDependencyException { 103 return resolveInClassLoader(source, Collections.EMPTY_SET); 104 } 105 106 public Artifact resolveInClassLoader(Artifact source, Collection parentConfigurations) throws MissingDependencyException { 107 // Some tests break if we acntually try to search for fully-resolved artifacts 108 if(source.isResolved()) { 109 return source; 110 } 111 // if (artifact.getType() == null) { 112 // throw new IllegalArgumentException("Type not set " + artifact); 113 // } 114 // 115 // String groupId = source.getGroupId(); 116 // if (groupId == null) { 117 // groupId = Artifact.DEFAULT_GROUP_ID; 118 // } 119 120 // Version version = source.getVersion(); 121 122 Artifact working = resolveVersion(parentConfigurations, source); 123 if (working == null || !working.isResolved()) { 124 throw new MissingDependencyException("Unable to resolve dependency " + source); 125 } 126 127 return working; 128 } 129 130 private Artifact resolveVersion(Collection parentConfigurations, Artifact working) { 131 //see if there is an explicit resolution for this artifact. 132 Artifact deAliased = (Artifact) explicitResolution.get(working); 133 if (deAliased != null) { 134 working = deAliased; 135 } 136 SortedSet existingArtifacts; 137 if (artifactManager != null) { 138 existingArtifacts = artifactManager.getLoadedArtifacts(working); 139 } else { 140 existingArtifacts = new TreeSet(); 141 } 142 143 // if we have exactly one artifact loaded use its' version 144 if (existingArtifacts.size() == 1) { 145 return (Artifact) existingArtifacts.first(); 146 } 147 148 149 // if we have no existing loaded artifacts grab the highest version from the repository 150 if (existingArtifacts.size() == 0) { 151 SortedSet list = new TreeSet(); 152 for (Iterator iterator = repositories.iterator(); iterator.hasNext();) { 153 ListableRepository repository = (ListableRepository) iterator.next(); 154 list.addAll(repository.list(working)); 155 } 156 157 if (list.isEmpty()) { 158 return null; 159 } 160 return (Artifact) list.last(); 161 } 162 163 // more than one version of the artifact was loaded... 164 165 // if one of parents already loaded the artifact, use that version 166 Artifact artifact = searchParents(parentConfigurations, working); 167 if (artifact != null) { 168 return artifact; 169 } 170 171 // it wasn't declared by the parent so just use the highest verstion already loaded 172 return (Artifact) existingArtifacts.last(); 173 } 174 175 private Artifact searchParents(Collection parentConfigurations, Artifact working) { 176 for (Iterator iterator = parentConfigurations.iterator(); iterator.hasNext();) { 177 Configuration configuration = (Configuration) iterator.next(); 178 179 // check if this parent matches the groupId, artifactId, and type 180 if (matches(configuration.getId(), working)) { 181 return configuration.getId(); 182 } 183 184 Environment environment = configuration.getEnvironment(); 185 if (environment.isInverseClassLoading()) { 186 // Search dependencies of the configuration before searching the parents 187 Artifact artifact = getArtifactVersion(configuration.getDependencies(), working); 188 if (artifact != null) { 189 return artifact; 190 } 191 192 // wasn't declared in the dependencies, so search the parents of the configuration 193 artifact = searchParents(configuration.getClassParents(), working); 194 if (artifact != null) { 195 return artifact; 196 } 197 198 } else { 199 // Search the parents before the dependencies of the configuration 200 Artifact artifact = searchParents(configuration.getClassParents(), working); 201 if (artifact != null) { 202 return artifact; 203 } 204 205 // wasn't declared in a parent check the dependencies of the configuration 206 artifact = getArtifactVersion(configuration.getDependencies(), working); 207 if (artifact != null) { 208 return artifact; 209 } 210 } 211 } 212 return null; 213 } 214 215 private Artifact getArtifactVersion(Collection artifacts, Artifact query) { 216 for (Iterator iterator = artifacts.iterator(); iterator.hasNext();) { 217 Artifact artifact = (Artifact) iterator.next(); 218 if (matches(artifact, query)) { 219 return artifact; 220 } 221 } 222 return null; 223 } 224 225 private boolean matches(Artifact candidate, Artifact query) { 226 return query.matches(candidate); 227 } 228 229 public static final GBeanInfo GBEAN_INFO; 230 231 static { 232 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(DefaultArtifactResolver.class, "ArtifactResolver"); 233 infoFactory.addAttribute("explicitResolution", Map.class, true, true); 234 infoFactory.addReference("ArtifactManager", ArtifactManager.class, "ArtifactManager"); 235 infoFactory.addReference("Repositories", ListableRepository.class, "Repository"); 236 infoFactory.addInterface(ArtifactResolver.class); 237 238 infoFactory.setConstructor(new String[]{ 239 "ArtifactManager", 240 "Repositories", 241 "explicitResolution" 242 }); 243 244 245 GBEAN_INFO = infoFactory.getBeanInfo(); 246 } 247 248 public static GBeanInfo getGBeanInfo() { 249 return GBEAN_INFO; 250 } 251 }