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 }