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.repository; 018 019 import java.util.Collection; 020 import java.util.Collections; 021 import java.util.Iterator; 022 import java.util.LinkedHashSet; 023 import java.util.SortedSet; 024 import java.util.TreeSet; 025 import java.util.Map; 026 027 import org.apache.geronimo.gbean.GBeanInfo; 028 import org.apache.geronimo.gbean.GBeanInfoBuilder; 029 import org.apache.geronimo.kernel.config.Configuration; 030 031 /** 032 * @version $Rev: 497146 $ $Date: 2007-01-17 15:03:23 -0500 (Wed, 17 Jan 2007) $ 033 */ 034 public class DefaultArtifactResolver implements ArtifactResolver { 035 private final ArtifactManager artifactManager; 036 private final Collection repositories; 037 private final Map explicitResolution; 038 039 public DefaultArtifactResolver(ArtifactManager artifactManager, ListableRepository repository) { 040 this.artifactManager = artifactManager; 041 this.repositories = Collections.singleton(repository); 042 this.explicitResolution = Collections.EMPTY_MAP; 043 } 044 045 public DefaultArtifactResolver(ArtifactManager artifactManager, Collection repositories, Map explicitResolution) { 046 this.artifactManager = artifactManager; 047 this.repositories = repositories; 048 this.explicitResolution = explicitResolution == null? Collections.EMPTY_MAP: explicitResolution; 049 } 050 051 052 public Artifact generateArtifact(Artifact source, String defaultType) { 053 if(source.isResolved()) { 054 Artifact deAliased = (Artifact) explicitResolution.get(source); 055 if (deAliased != null) { 056 return deAliased; 057 } 058 return source; 059 } 060 String groupId = source.getGroupId() == null ? Artifact.DEFAULT_GROUP_ID : source.getGroupId(); 061 String artifactId = source.getArtifactId(); 062 String type = source.getType() == null ? defaultType : source.getType(); 063 Version version = source.getVersion() == null ? new Version(Long.toString(System.currentTimeMillis())) : source.getVersion(); 064 065 return new Artifact(groupId, artifactId, version, type); 066 } 067 068 public Artifact queryArtifact(Artifact artifact) throws MultipleMatchesException { 069 Artifact[] all = queryArtifacts(artifact); 070 if(all.length > 1) { 071 throw new MultipleMatchesException(artifact); 072 } 073 return all.length == 0 ? null : all[0]; 074 } 075 076 public Artifact[] queryArtifacts(Artifact artifact) { 077 LinkedHashSet set = new LinkedHashSet(); 078 for (Iterator iterator = repositories.iterator(); iterator.hasNext();) { 079 ListableRepository repository = (ListableRepository) iterator.next(); 080 set.addAll(repository.list(artifact)); 081 } 082 return (Artifact[]) set.toArray(new Artifact[set.size()]); 083 } 084 085 public LinkedHashSet resolveInClassLoader(Collection artifacts) throws MissingDependencyException { 086 return resolveInClassLoader(artifacts, Collections.EMPTY_SET); 087 } 088 089 public LinkedHashSet resolveInClassLoader(Collection artifacts, Collection parentConfigurations) throws MissingDependencyException { 090 LinkedHashSet resolvedArtifacts = new LinkedHashSet(); 091 for (Iterator iterator = artifacts.iterator(); iterator.hasNext();) { 092 Artifact artifact = (Artifact) iterator.next(); 093 if (!artifact.isResolved()) { 094 artifact = resolveInClassLoader(artifact, parentConfigurations); 095 } 096 resolvedArtifacts.add(artifact); 097 } 098 return resolvedArtifacts; 099 } 100 101 public Artifact resolveInClassLoader(Artifact source) throws MissingDependencyException { 102 return resolveInClassLoader(source, Collections.EMPTY_SET); 103 } 104 105 public Artifact resolveInClassLoader(Artifact source, Collection parentConfigurations) throws MissingDependencyException { 106 // Some tests break if we acntually try to search for fully-resolved artifacts 107 if(source.isResolved()) { 108 return source; 109 } 110 // if (artifact.getType() == null) { 111 // throw new IllegalArgumentException("Type not set " + artifact); 112 // } 113 // 114 // String groupId = source.getGroupId(); 115 // if (groupId == null) { 116 // groupId = Artifact.DEFAULT_GROUP_ID; 117 // } 118 119 // Version version = source.getVersion(); 120 121 Artifact working = resolveVersion(parentConfigurations, source); 122 if (working == null || !working.isResolved()) { 123 throw new MissingDependencyException("Unable to resolve dependency " + source); 124 } 125 126 return working; 127 } 128 129 private Artifact resolveVersion(Collection parentConfigurations, Artifact working) { 130 //see if there is an explicit resolution for this artifact. 131 Artifact deAliased = (Artifact) explicitResolution.get(working); 132 if (deAliased != null) { 133 working = deAliased; 134 } 135 SortedSet existingArtifacts; 136 if (artifactManager != null) { 137 existingArtifacts = artifactManager.getLoadedArtifacts(working); 138 } else { 139 existingArtifacts = new TreeSet(); 140 } 141 142 // if we have exactly one artifact loaded use its' version 143 if (existingArtifacts.size() == 1) { 144 return (Artifact) existingArtifacts.first(); 145 } 146 147 148 // if we have no existing loaded artifacts grab the highest version from the repository 149 if (existingArtifacts.size() == 0) { 150 SortedSet list = new TreeSet(); 151 for (Iterator iterator = repositories.iterator(); iterator.hasNext();) { 152 ListableRepository repository = (ListableRepository) iterator.next(); 153 list.addAll(repository.list(working)); 154 } 155 156 if (list.isEmpty()) { 157 if ("xbean-naming".equals(working.getArtifactId())) { 158 return new Artifact("org.apache.xbean", "xbean-naming", "2.8", "jar"); 159 } else { 160 return null; 161 } 162 } 163 return (Artifact) list.last(); 164 } 165 166 // more than one version of the artifact was loaded... 167 168 // if one of parents already loaded the artifact, use that version 169 Artifact artifact = searchParents(parentConfigurations, working); 170 if (artifact != null) { 171 return artifact; 172 } 173 174 // it wasn't declared by the parent so just use the highest verstion already loaded 175 return (Artifact) existingArtifacts.last(); 176 } 177 178 private Artifact searchParents(Collection parentConfigurations, Artifact working) { 179 for (Iterator iterator = parentConfigurations.iterator(); iterator.hasNext();) { 180 Configuration configuration = (Configuration) iterator.next(); 181 182 // check if this parent matches the groupId, artifactId, and type 183 if (matches(configuration.getId(), working)) { 184 return configuration.getId(); 185 } 186 187 Environment environment = configuration.getEnvironment(); 188 if (environment.isInverseClassLoading()) { 189 // Search dependencies of the configuration before searching the parents 190 Artifact artifact = getArtifactVersion(configuration.getDependencies(), working); 191 if (artifact != null) { 192 return artifact; 193 } 194 195 // wasn't declared in the dependencies, so search the parents of the configuration 196 artifact = searchParents(configuration.getClassParents(), working); 197 if (artifact != null) { 198 return artifact; 199 } 200 201 } else { 202 // Search the parents before the dependencies of the configuration 203 Artifact artifact = searchParents(configuration.getClassParents(), working); 204 if (artifact != null) { 205 return artifact; 206 } 207 208 // wasn't declared in a parent check the dependencies of the configuration 209 artifact = getArtifactVersion(configuration.getDependencies(), working); 210 if (artifact != null) { 211 return artifact; 212 } 213 } 214 } 215 return null; 216 } 217 218 private Artifact getArtifactVersion(Collection artifacts, Artifact query) { 219 for (Iterator iterator = artifacts.iterator(); iterator.hasNext();) { 220 Artifact artifact = (Artifact) iterator.next(); 221 if (matches(artifact, query)) { 222 return artifact; 223 } 224 } 225 return null; 226 } 227 228 private boolean matches(Artifact candidate, Artifact query) { 229 return query.matches(candidate); 230 } 231 232 public static final GBeanInfo GBEAN_INFO; 233 234 static { 235 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(DefaultArtifactResolver.class, "ArtifactResolver"); 236 infoFactory.addAttribute("explicitResolution", Map.class, true, true); 237 infoFactory.addReference("ArtifactManager", ArtifactManager.class, "ArtifactManager"); 238 infoFactory.addReference("Repositories", ListableRepository.class, "Repository"); 239 infoFactory.addInterface(ArtifactResolver.class); 240 241 infoFactory.setConstructor(new String[]{ 242 "ArtifactManager", 243 "Repositories", 244 "explicitResolution" 245 }); 246 247 248 GBEAN_INFO = infoFactory.getBeanInfo(); 249 } 250 251 public static GBeanInfo getGBeanInfo() { 252 return GBEAN_INFO; 253 } 254 }