View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  package org.apache.geronimo.kernel.repository;
19  
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.Iterator;
23  import java.util.LinkedHashSet;
24  import java.util.SortedSet;
25  import java.util.TreeSet;
26  import java.util.Map;
27  
28  import org.apache.geronimo.gbean.GBeanInfo;
29  import org.apache.geronimo.gbean.GBeanInfoBuilder;
30  import org.apache.geronimo.kernel.config.Configuration;
31  
32  /**
33   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
34   */
35  public class DefaultArtifactResolver implements ArtifactResolver {
36      private final ArtifactManager artifactManager;
37      private final Collection repositories;
38      private final Map explicitResolution;
39  
40      public DefaultArtifactResolver(ArtifactManager artifactManager, ListableRepository repository) {
41          this.artifactManager = artifactManager;
42          this.repositories = Collections.singleton(repository);
43          this.explicitResolution = Collections.EMPTY_MAP;
44      }
45  
46      public DefaultArtifactResolver(ArtifactManager artifactManager, Collection repositories, Map explicitResolution) {
47          this.artifactManager = artifactManager;
48          this.repositories = repositories;
49          this.explicitResolution = explicitResolution == null? Collections.EMPTY_MAP: explicitResolution;
50      }
51  
52  
53      public Artifact generateArtifact(Artifact source, String defaultType) {
54          if(source.isResolved()) {
55              Artifact deAliased = (Artifact) explicitResolution.get(source);
56              if (deAliased !=  null) {
57                  return deAliased;
58              }
59              return source;
60          }
61          String groupId = source.getGroupId() == null ? Artifact.DEFAULT_GROUP_ID : source.getGroupId();
62          String artifactId = source.getArtifactId();
63          String type = source.getType() == null ? defaultType : source.getType();
64          Version version = source.getVersion() == null ? new Version(Long.toString(System.currentTimeMillis())) : source.getVersion();
65  
66          return new Artifact(groupId, artifactId, version, type);
67      }
68  
69      public Artifact queryArtifact(Artifact artifact) throws MultipleMatchesException {
70          Artifact[] all = queryArtifacts(artifact);
71          if(all.length > 1) {
72              throw new MultipleMatchesException(artifact);
73          }
74          return all.length == 0 ? null : all[0];
75      }
76  
77      public Artifact[] queryArtifacts(Artifact artifact) {
78          LinkedHashSet set = new LinkedHashSet();
79          for (Iterator iterator = repositories.iterator(); iterator.hasNext();) {
80              ListableRepository repository = (ListableRepository) iterator.next();
81              set.addAll(repository.list(artifact));
82          }
83          return (Artifact[]) set.toArray(new Artifact[set.size()]);
84      }
85  
86      public LinkedHashSet resolveInClassLoader(Collection artifacts) throws MissingDependencyException {
87          return resolveInClassLoader(artifacts, Collections.EMPTY_SET);
88      }
89  
90      public LinkedHashSet resolveInClassLoader(Collection artifacts, Collection parentConfigurations) throws MissingDependencyException {
91          LinkedHashSet resolvedArtifacts = new LinkedHashSet();
92          for (Iterator iterator = artifacts.iterator(); iterator.hasNext();) {
93              Artifact artifact = (Artifact) iterator.next();
94              if (!artifact.isResolved()) {
95                  artifact = resolveInClassLoader(artifact, parentConfigurations);
96              }
97              resolvedArtifacts.add(artifact);
98          }
99          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 }