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 }