KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fr > jayasoft > ivy > Ivy


1 /*
2  * This file is subject to the license found in LICENCE.TXT in the root directory of the project.
3  *
4  * #SNAPSHOT#
5  */

6 package fr.jayasoft.ivy;
7
8 import java.io.File JavaDoc;
9 import java.io.FileInputStream JavaDoc;
10 import java.io.FileNotFoundException JavaDoc;
11 import java.io.FileOutputStream JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.io.InputStream JavaDoc;
14 import java.net.InetAddress JavaDoc;
15 import java.net.MalformedURLException JavaDoc;
16 import java.net.URL JavaDoc;
17 import java.net.URLClassLoader JavaDoc;
18 import java.net.UnknownHostException JavaDoc;
19 import java.text.ParseException JavaDoc;
20 import java.text.SimpleDateFormat JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Arrays JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.Comparator JavaDoc;
26 import java.util.Date JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.HashSet JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.LinkedHashMap JavaDoc;
31 import java.util.LinkedHashSet JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.ListIterator JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Properties JavaDoc;
36 import java.util.Set JavaDoc;
37 import java.util.StringTokenizer JavaDoc;
38
39 import javax.swing.event.EventListenerList JavaDoc;
40
41 import org.xml.sax.SAXException JavaDoc;
42
43 import fr.jayasoft.ivy.IvyNode.EvictionData;
44 import fr.jayasoft.ivy.circular.CircularDependencyStrategy;
45 import fr.jayasoft.ivy.circular.ErrorCircularDependencyStrategy;
46 import fr.jayasoft.ivy.circular.IgnoreCircularDependencyStrategy;
47 import fr.jayasoft.ivy.circular.WarnCircularDependencyStrategy;
48 import fr.jayasoft.ivy.conflict.LatestConflictManager;
49 import fr.jayasoft.ivy.conflict.NoConflictManager;
50 import fr.jayasoft.ivy.conflict.StrictConflictManager;
51 import fr.jayasoft.ivy.event.FilteredIvyListener;
52 import fr.jayasoft.ivy.event.IvyEvent;
53 import fr.jayasoft.ivy.event.IvyEventFilter;
54 import fr.jayasoft.ivy.event.IvyListener;
55 import fr.jayasoft.ivy.event.Trigger;
56 import fr.jayasoft.ivy.event.download.PrepareDownloadEvent;
57 import fr.jayasoft.ivy.event.resolve.EndResolveEvent;
58 import fr.jayasoft.ivy.event.resolve.StartResolveEvent;
59 import fr.jayasoft.ivy.filter.Filter;
60 import fr.jayasoft.ivy.filter.FilterHelper;
61 import fr.jayasoft.ivy.latest.LatestLexicographicStrategy;
62 import fr.jayasoft.ivy.latest.LatestRevisionStrategy;
63 import fr.jayasoft.ivy.latest.LatestTimeStrategy;
64 import fr.jayasoft.ivy.matcher.ExactOrRegexpPatternMatcher;
65 import fr.jayasoft.ivy.matcher.ExactPatternMatcher;
66 import fr.jayasoft.ivy.matcher.GlobPatternMatcher;
67 import fr.jayasoft.ivy.matcher.Matcher;
68 import fr.jayasoft.ivy.matcher.MatcherHelper;
69 import fr.jayasoft.ivy.matcher.ModuleIdMatcher;
70 import fr.jayasoft.ivy.matcher.PatternMatcher;
71 import fr.jayasoft.ivy.matcher.RegexpPatternMatcher;
72 import fr.jayasoft.ivy.namespace.NameSpaceHelper;
73 import fr.jayasoft.ivy.namespace.Namespace;
74 import fr.jayasoft.ivy.parser.ModuleDescriptorParser;
75 import fr.jayasoft.ivy.parser.ModuleDescriptorParserRegistry;
76 import fr.jayasoft.ivy.report.ArtifactDownloadReport;
77 import fr.jayasoft.ivy.report.ConfigurationResolveReport;
78 import fr.jayasoft.ivy.report.DownloadReport;
79 import fr.jayasoft.ivy.report.DownloadStatus;
80 import fr.jayasoft.ivy.report.LogReportOutputter;
81 import fr.jayasoft.ivy.report.ReportOutputter;
82 import fr.jayasoft.ivy.report.ResolveReport;
83 import fr.jayasoft.ivy.report.XmlReportOutputter;
84 import fr.jayasoft.ivy.repository.TransferEvent;
85 import fr.jayasoft.ivy.repository.TransferListener;
86 import fr.jayasoft.ivy.repository.url.URLResource;
87 import fr.jayasoft.ivy.resolver.AbstractResolver;
88 import fr.jayasoft.ivy.resolver.CacheResolver;
89 import fr.jayasoft.ivy.resolver.ChainResolver;
90 import fr.jayasoft.ivy.resolver.DualResolver;
91 import fr.jayasoft.ivy.resolver.ModuleEntry;
92 import fr.jayasoft.ivy.resolver.OrganisationEntry;
93 import fr.jayasoft.ivy.resolver.RevisionEntry;
94 import fr.jayasoft.ivy.status.StatusManager;
95 import fr.jayasoft.ivy.url.URLHandlerRegistry;
96 import fr.jayasoft.ivy.util.FileUtil;
97 import fr.jayasoft.ivy.util.IvyPatternHelper;
98 import fr.jayasoft.ivy.util.Message;
99 import fr.jayasoft.ivy.util.PropertiesFile;
100 import fr.jayasoft.ivy.version.ChainVersionMatcher;
101 import fr.jayasoft.ivy.version.ExactVersionMatcher;
102 import fr.jayasoft.ivy.version.LatestVersionMatcher;
103 import fr.jayasoft.ivy.version.SubVersionMatcher;
104 import fr.jayasoft.ivy.version.VersionMatcher;
105 import fr.jayasoft.ivy.version.VersionRangeMatcher;
106 import fr.jayasoft.ivy.xml.XmlIvyConfigurationParser;
107 import fr.jayasoft.ivy.xml.XmlModuleDescriptorParser;
108 import fr.jayasoft.ivy.xml.XmlModuleDescriptorUpdater;
109 import fr.jayasoft.ivy.xml.XmlReportParser;
110
111 /**
112  * <a HREF="http://www.jayasoft.org/ivy">Ivy</a> is a free java based dependency manager.
113  *
114  * This class is the main class of Ivy, which offers mainly dependency resolution.
115  *
116  * Here is one typical usage:
117  * Ivy ivy = new Ivy();
118  * ivy.configure(new URL("ivyconf.xml"));
119  * ivy.resolve(new URL("ivy.xml"));
120  *
121  * @author Xavier Hanin
122  *
123  */

124 public class Ivy implements TransferListener {
125
126     public static Ivy getCurrent() {
127         Ivy cur = IvyContext.getContext().getIvy();
128         if (cur == null) {
129             cur = new Ivy();
130             IvyContext.getContext().setIvy(cur);
131         }
132         return cur;
133     }
134
135     
136     public static final SimpleDateFormat JavaDoc DATE_FORMAT = new SimpleDateFormat JavaDoc("yyyyMMddHHmmss");
137
138     private static final String JavaDoc DEFAULT_CACHE_ARTIFACT_PATTERN = "[organisation]/[module]/[type]s/[artifact]-[revision](.[ext])";
139     private static final String JavaDoc DEFAULT_CACHE_DATA_FILE_PATTERN = "[organisation]/[module]/ivydata-[revision].properties";
140     private static final String JavaDoc DEFAULT_CACHE_IVY_PATTERN = "[organisation]/[module]/ivy-[revision].xml";
141     private static final String JavaDoc DEFAULT_CACHE_RESOLVED_IVY_PATTERN = "resolved-[organisation]-[module]-[revision].xml";
142     private static final String JavaDoc DEFAULT_CACHE_RESOLVED_IVY_PROPERTIES_PATTERN = "resolved-[organisation]-[module]-[revision].properties";
143     
144     private Map JavaDoc _typeDefs = new HashMap JavaDoc();
145     private Map JavaDoc _resolversMap = new HashMap JavaDoc();
146     private DependencyResolver _defaultResolver;
147     private DependencyResolver _dictatorResolver = null;
148     
149     private String JavaDoc _defaultResolverName;
150     private File JavaDoc _defaultCache;
151
152     private String JavaDoc _defaultBranch = null;
153
154     private boolean _checkUpToDate = true;
155     private Map JavaDoc _moduleConfigurations = new LinkedHashMap JavaDoc(); // Map (ModuleIdMatcher -> ModuleSettings)
156

157     private Map JavaDoc _conflictsManager = new HashMap JavaDoc(); // Map (String conflictManagerName -> ConflictManager)
158
private Map JavaDoc _latestStrategies = new HashMap JavaDoc(); // Map (String latestStrategyName -> LatestStrategy)
159
private Map JavaDoc _namespaces = new HashMap JavaDoc(); // Map (String namespaceName -> Namespace)
160
private Map JavaDoc _matchers = new HashMap JavaDoc(); // Map (String matcherName -> Matcher)
161
private Map JavaDoc _reportOutputters = new HashMap JavaDoc(); // Map (String outputterName -> ReportOutputter)
162
private Map JavaDoc _versionMatchers = new HashMap JavaDoc(); // Map (String matcherName -> VersionMatcher)
163
private Map JavaDoc _circularDependencyStrategies = new HashMap JavaDoc(); // Map (String name -> CircularDependencyStrategy)
164

165     private Map JavaDoc _variables = new HashMap JavaDoc();
166
167     private String JavaDoc _cacheIvyPattern = DEFAULT_CACHE_IVY_PATTERN;
168     private String JavaDoc _cacheResolvedIvyPattern = DEFAULT_CACHE_RESOLVED_IVY_PATTERN;
169     private String JavaDoc _cacheResolvedIvyPropertiesPattern = DEFAULT_CACHE_RESOLVED_IVY_PROPERTIES_PATTERN;
170     private String JavaDoc _cacheArtifactPattern = DEFAULT_CACHE_ARTIFACT_PATTERN;
171     private String JavaDoc _cacheDataFilePattern = DEFAULT_CACHE_DATA_FILE_PATTERN;
172
173     private boolean _validate = true;
174
175     private LatestStrategy _defaultLatestStrategy = null;
176     private ConflictManager _defaultConflictManager = null;
177     private CircularDependencyStrategy _circularDependencyStrategy = null;
178     
179     private List JavaDoc _listingIgnore = new ArrayList JavaDoc();
180
181     private boolean _repositoriesConfigured;
182
183     private boolean _useRemoteConfig = false;
184
185     private File JavaDoc _defaultUserDir;
186     
187     private Set JavaDoc _fetchedSet = new HashSet JavaDoc();
188
189     private List JavaDoc _classpathURLs = new ArrayList JavaDoc();
190
191     private ClassLoader JavaDoc _classloader;
192     
193     private StatusManager _statusManager;
194
195     private long _interruptTimeout = 2000;
196
197     private boolean _interrupted;
198     
199     public Ivy() {
200         setVariable("ivy.default.conf.dir", Ivy.class.getResource("conf").toExternalForm(), true);
201         
202         String JavaDoc ivyTypeDefs = System.getProperty("ivy.typedef.files");
203         if (ivyTypeDefs != null) {
204             String JavaDoc[] files = ivyTypeDefs.split("\\,");
205             for (int i = 0; i < files.length; i++) {
206                 try {
207                     typeDefs(new FileInputStream JavaDoc(new File JavaDoc(files[i].trim())), true);
208                 } catch (FileNotFoundException JavaDoc e) {
209                     Message.warn("typedefs file not found: "+files[i].trim());
210                 } catch (IOException JavaDoc e) {
211                     Message.warn("problem with typedef file: "+files[i].trim()+": "+e.getMessage());
212                 }
213             }
214         } else {
215             try {
216                 typeDefs(Ivy.class.getResourceAsStream("typedef.properties"), true);
217             } catch (IOException JavaDoc e) {
218                 Message.warn("impossible to load default type defs");
219             }
220         }
221         LatestLexicographicStrategy latestLexicographicStrategy = new LatestLexicographicStrategy();
222         LatestRevisionStrategy latestRevisionStrategy = new LatestRevisionStrategy();
223         LatestTimeStrategy latestTimeStrategy = new LatestTimeStrategy();
224
225         addLatestStrategy("latest-revision", latestRevisionStrategy);
226         addLatestStrategy("latest-lexico", latestLexicographicStrategy);
227         addLatestStrategy("latest-time", latestTimeStrategy);
228
229         addConflictManager("latest-revision", new LatestConflictManager("latest-revision", latestRevisionStrategy));
230         addConflictManager("latest-time", new LatestConflictManager("latest-time", latestTimeStrategy));
231         addConflictManager("all", new NoConflictManager());
232         addConflictManager("strict", new StrictConflictManager());
233         
234         addMatcher(ExactPatternMatcher.getInstance());
235         addMatcher(RegexpPatternMatcher.getInstance());
236         addMatcher(ExactOrRegexpPatternMatcher.getInstance());
237         addMatcher(GlobPatternMatcher.getInstance());
238         
239         addReportOutputter(new XmlReportOutputter());
240         addReportOutputter(new LogReportOutputter());
241         
242         configureDefaultCircularDependencyStrategies();
243         
244         _listingIgnore.add(".cvsignore");
245         _listingIgnore.add("CVS");
246         _listingIgnore.add(".svn");
247         
248         addSystemProperties();
249         
250         addTransferListener(new TransferListener() {
251             public void transferProgress(TransferEvent evt) {
252                 switch (evt.getEventType()) {
253                 case TransferEvent.TRANSFER_PROGRESS:
254                     Message.progress();
255                     break;
256                 case TransferEvent.TRANSFER_COMPLETED:
257                     Message.endProgress(" ("+(evt.getTotalLength() / 1024)+"kB)");
258                     break;
259                 default:
260                     break;
261                 }
262             }
263         });
264         IvyContext.getContext().setIvy(this);
265     }
266     
267     private void addSystemProperties() {
268         addAllVariables(System.getProperties());
269     }
270
271     /**
272      * Call this method to ask ivy to configure some variables using either a remote or a local properties file
273      */

274     public void configureRepositories(boolean remote) {
275         IvyContext.getContext().setIvy(this);
276         if (!_repositoriesConfigured) {
277             Properties JavaDoc props = new Properties JavaDoc();
278             boolean configured = false;
279             if (_useRemoteConfig && remote) {
280                 try {
281                     URL JavaDoc url = new URL JavaDoc("http://www.jayasoft.org/ivy/repository.properties");
282                     Message.verbose("configuring repositories with "+url);
283                     props.load(URLHandlerRegistry.getDefault().openStream(url));
284                     configured = true;
285                 } catch (Exception JavaDoc ex) {
286                     Message.verbose("unable to use remote repository configuration: "+ex.getMessage());
287                     props = new Properties JavaDoc();
288                 }
289             }
290             if (!configured) {
291                 try {
292                     props.load(Ivy.class.getResourceAsStream("repository.properties"));
293                 } catch (IOException JavaDoc e) {
294                     Message.error("unable to use internal repository configuration: "+e.getMessage());
295                 }
296             }
297             addAllVariables(props, false);
298             _repositoriesConfigured = true;
299         }
300     }
301
302
303     public void typeDefs(InputStream JavaDoc stream) throws IOException JavaDoc {
304         typeDefs(stream, false);
305     }
306     public void typeDefs(InputStream JavaDoc stream, boolean silentFail) throws IOException JavaDoc {
307         IvyContext.getContext().setIvy(this);
308         try {
309             Properties JavaDoc p = new Properties JavaDoc();
310             p.load(stream);
311             typeDefs(p, silentFail);
312         } finally {
313             stream.close();
314         }
315     }
316
317     public void typeDefs(Properties JavaDoc p) {
318         typeDefs(p, false);
319     }
320     public void typeDefs(Properties JavaDoc p, boolean silentFail) {
321         IvyContext.getContext().setIvy(this);
322         for (Iterator JavaDoc iter = p.keySet().iterator(); iter.hasNext();) {
323             String JavaDoc name = (String JavaDoc) iter.next();
324             typeDef(name, p.getProperty(name), silentFail);
325         }
326     }
327     
328     
329     /////////////////////////////////////////////////////////////////////////
330
// CONFIGURATION
331
/////////////////////////////////////////////////////////////////////////
332
public void configure(File JavaDoc configurationFile) throws ParseException JavaDoc, IOException JavaDoc {
333         IvyContext.getContext().setIvy(this);
334         Message.info(":: configuring :: file = "+configurationFile);
335         long start = System.currentTimeMillis();
336         setConfigurationVariables(configurationFile);
337         if (getVariable("ivy.default.ivy.user.dir") != null) {
338             setDefaultIvyUserDir(new File JavaDoc(getVariable("ivy.default.ivy.user.dir")));
339         } else {
340             getDefaultIvyUserDir();
341         }
342         getDefaultCache();
343         
344         loadDefaultProperties();
345         try {
346             new XmlIvyConfigurationParser(this).parse(configurationFile.toURL());
347         } catch (MalformedURLException JavaDoc e) {
348             IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc("given file cannot be transformed to url: "+configurationFile);
349             iae.initCause(e);
350             throw iae;
351         }
352         setVariable("ivy.default.ivy.user.dir", getDefaultIvyUserDir().getAbsolutePath(), false);
353         Message.verbose("configuration done ("+(System.currentTimeMillis()-start)+"ms)");
354         dumpConfig();
355     }
356
357     public void configure(URL JavaDoc configurationURL) throws ParseException JavaDoc, IOException JavaDoc {
358         IvyContext.getContext().setIvy(this);
359         Message.info(":: configuring :: url = "+configurationURL);
360         long start = System.currentTimeMillis();
361         setConfigurationVariables(configurationURL);
362         if (getVariable("ivy.default.ivy.user.dir") != null) {
363             setDefaultIvyUserDir(new File JavaDoc(getVariable("ivy.default.ivy.user.dir")));
364         } else {
365             getDefaultIvyUserDir();
366         }
367         getDefaultCache();
368         
369         loadDefaultProperties();
370         new XmlIvyConfigurationParser(this).parse(configurationURL);
371         setVariable("ivy.default.ivy.user.dir", getDefaultIvyUserDir().getAbsolutePath(), false);
372         Message.verbose("configuration done ("+(System.currentTimeMillis()-start)+"ms)");
373         dumpConfig();
374     }
375
376     private void loadDefaultProperties() throws IOException JavaDoc {
377         loadProperties(Ivy.class.getResource("ivy.properties"), false);
378     }
379
380     public void configureDefault() throws ParseException JavaDoc, IOException JavaDoc {
381         configure(getDefaultConfigurationURL());
382     }
383
384     public void setConfigurationVariables(File JavaDoc configurationFile) {
385         IvyContext.getContext().setIvy(this);
386         try {
387             setVariable("ivy.conf.dir", new File JavaDoc(configurationFile.getAbsolutePath()).getParent());
388             setVariable("ivy.conf.file", configurationFile.getAbsolutePath());
389             setVariable("ivy.conf.url", configurationFile.toURL().toExternalForm());
390         } catch (MalformedURLException JavaDoc e) {
391             IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc("given file cannot be transformed to url: "+configurationFile);
392             iae.initCause(e);
393             throw iae;
394         }
395     }
396     
397     public void setConfigurationVariables(URL JavaDoc configurationURL) {
398         IvyContext.getContext().setIvy(this);
399         String JavaDoc confURL = configurationURL.toExternalForm();
400         setVariable("ivy.conf.url", confURL);
401         int slashIndex = confURL.lastIndexOf('/');
402         if (slashIndex != -1) {
403             setVariable("ivy.conf.dir", confURL.substring(0, slashIndex));
404         } else {
405             Message.warn("configuration url does not contain any slash (/): ivy.conf.dir variable not set");
406         }
407     }
408     
409     private void dumpConfig() {
410         Message.verbose("\tdefault cache: "+getDefaultCache());
411         Message.verbose("\tdefault resolver: "+getDefaultResolver());
412         Message.debug("\tdefault latest strategy: "+getDefaultLatestStrategy());
413         Message.debug("\tdefault conflict manager: "+getDefaultConflictManager());
414         Message.debug("\tcircular dependency strategy: "+getCircularDependencyStrategy());
415         Message.debug("\tvalidate: "+doValidate());
416         Message.debug("\tcheck up2date: "+isCheckUpToDate());
417         Message.debug("\tcache ivy pattern: "+getCacheIvyPattern());
418         Message.debug("\tcache artifact pattern: "+getCacheArtifactPattern());
419         
420         if (!_classpathURLs.isEmpty()) {
421             Message.verbose("\t-- "+_classpathURLs.size()+" custom classpath urls:");
422             for (Iterator JavaDoc iter = _classpathURLs.iterator(); iter.hasNext();) {
423                 Message.debug("\t\t"+iter.next());
424             }
425         }
426         Message.verbose("\t-- "+_resolversMap.size()+" resolvers:");
427         for (Iterator JavaDoc iter = _resolversMap.values().iterator(); iter.hasNext();) {
428             DependencyResolver resolver = (DependencyResolver)iter.next();
429             resolver.dumpConfig();
430         }
431         if (!_moduleConfigurations.isEmpty()) {
432             Message.debug("\tmodule configurations:");
433             for (Iterator JavaDoc iter = _moduleConfigurations.keySet().iterator(); iter.hasNext();) {
434                 ModuleIdMatcher midm = (ModuleIdMatcher)iter.next();
435                 ModuleSettings s = (ModuleSettings)_moduleConfigurations.get(midm);
436                 Message.debug("\t\t"+midm+" -> "+s);
437             }
438         }
439     }
440
441     public void loadProperties(URL JavaDoc url) throws IOException JavaDoc {
442         loadProperties(url, true);
443     }
444     public void loadProperties(URL JavaDoc url, boolean overwrite) throws IOException JavaDoc {
445         loadProperties(url.openStream(), overwrite);
446     }
447     public void loadProperties(File JavaDoc file) throws IOException JavaDoc {
448         loadProperties(file, true);
449     }
450     
451     public void loadProperties(File JavaDoc file, boolean overwrite) throws IOException JavaDoc {
452         loadProperties(new FileInputStream JavaDoc(file), overwrite);
453     }
454     
455     private void loadProperties(InputStream JavaDoc stream, boolean overwrite) throws IOException JavaDoc {
456         try {
457             Properties JavaDoc properties = new Properties JavaDoc();
458             properties.load(stream);
459             addAllVariables(properties, overwrite);
460         } finally {
461             if (stream != null) {
462                 try {
463                     stream.close();
464                 } catch (IOException JavaDoc e) {}
465             }
466         }
467     }
468     
469     public void setVariable(String JavaDoc varName, String JavaDoc value) {
470         setVariable(varName, value, true);
471     }
472     
473     public void setVariable(String JavaDoc varName, String JavaDoc value, boolean overwrite) {
474         if (overwrite || !_variables.containsKey(varName)) {
475             Message.debug("setting '"+varName+"' to '"+value+"'");
476             _variables.put(varName, substitute(value));
477         } else {
478             Message.debug("'"+varName+"' already set: discarding '"+value+"'");
479         }
480     }
481     
482     public void addAllVariables(Map JavaDoc variables) {
483         addAllVariables(variables, true);
484     }
485
486     public void addAllVariables(Map JavaDoc variables, boolean overwrite) {
487         for (Iterator JavaDoc iter = variables.keySet().iterator(); iter.hasNext();) {
488             String JavaDoc key = (String JavaDoc)iter.next();
489             String JavaDoc val = (String JavaDoc)variables.get(key);
490             setVariable(key, val, overwrite);
491         }
492     }
493
494     /**
495      * Substitute variables in the given string by their value found in the current
496      * set of variables
497      *
498      * @param str the string in which substitution should be made
499      * @return the string where all current ivy variables have been substituted by their value
500      */

501     public String JavaDoc substitute(String JavaDoc str) {
502         return IvyPatternHelper.substituteVariables(str, getVariables());
503     }
504
505     /**
506      * Returns the variables loaded in configuration file. Those variables
507      * may better be seen as ant properties
508      *
509      * @return
510      */

511     public Map JavaDoc getVariables() {
512         return _variables;
513     }
514
515     public Class JavaDoc typeDef(String JavaDoc name, String JavaDoc className) {
516         return typeDef(name, className, false);
517     }
518     
519     public Class JavaDoc typeDef(String JavaDoc name, String JavaDoc className, boolean silentFail) {
520         Class JavaDoc clazz = classForName(className, silentFail);
521         if (clazz != null) {
522             _typeDefs.put(name, clazz);
523         }
524         return clazz;
525     }
526     
527     private Class JavaDoc classForName(String JavaDoc className, boolean silentFail) {
528         try {
529             return getClassLoader().loadClass(className);
530         } catch (ClassNotFoundException JavaDoc e) {
531             if (silentFail) {
532                 Message.info("impossible to define new type: class not found: "+className+" in "+_classpathURLs+" nor Ivy classloader");
533                 return null;
534             } else {
535                 throw new RuntimeException JavaDoc("impossible to define new type: class not found: "+className+" in "+_classpathURLs+" nor Ivy classloader");
536             }
537         }
538     }
539
540     private ClassLoader JavaDoc getClassLoader() {
541         if (_classloader == null) {
542             if (_classpathURLs.isEmpty()) {
543                 _classloader = Ivy.class.getClassLoader();
544             } else {
545                 _classloader = new URLClassLoader JavaDoc(
546                         (URL JavaDoc[])_classpathURLs.toArray(new URL JavaDoc[_classpathURLs.size()]),
547                         Ivy.class.getClassLoader());
548             }
549         }
550         return _classloader;
551     }
552
553
554     public void addClasspathURL(URL JavaDoc url) {
555         _classpathURLs.add(url);
556         _classloader = null;
557     }
558
559     public Map JavaDoc getTypeDefs() {
560         return _typeDefs;
561     }
562
563     public Class JavaDoc getTypeDef(String JavaDoc name) {
564         return (Class JavaDoc)_typeDefs.get(name);
565     }
566
567     // methods which match ivy conf method signature specs
568
public void addConfigured(DependencyResolver resolver) {
569         addResolver(resolver);
570     }
571     
572     public void addConfigured(ModuleDescriptorParser parser) {
573         ModuleDescriptorParserRegistry.getInstance().addParser(parser);
574     }
575     
576     public void addResolver(DependencyResolver resolver) {
577         if (resolver == null) {
578             throw new NullPointerException JavaDoc("null resolver");
579         }
580         if (resolver instanceof IvyAware) {
581             ((IvyAware)resolver).setIvy(this);
582         }
583         _resolversMap.put(resolver.getName(), resolver);
584         if (resolver instanceof ChainResolver) {
585             List JavaDoc subresolvers = ((ChainResolver)resolver).getResolvers();
586             for (Iterator JavaDoc iter = subresolvers.iterator(); iter.hasNext();) {
587                 DependencyResolver dr = (DependencyResolver)iter.next();
588                 addResolver(dr);
589             }
590         } else if (resolver instanceof DualResolver) {
591             DependencyResolver ivyResolver = ((DualResolver)resolver).getIvyResolver();
592             if (ivyResolver != null) {
593                 addResolver(ivyResolver);
594             }
595             DependencyResolver artifactResolver = ((DualResolver)resolver).getArtifactResolver();
596             if (artifactResolver != null) {
597                 addResolver(artifactResolver);
598             }
599         }
600     }
601     
602     public void setDefaultCache(File JavaDoc cacheDirectory) {
603         _defaultCache = cacheDirectory;
604     }
605     
606     public void setDefaultResolver(String JavaDoc resolverName) {
607         checkResolverName(resolverName);
608         _defaultResolverName = resolverName;
609     }
610     
611     private void checkResolverName(String JavaDoc resolverName) {
612         if (resolverName != null && !_resolversMap.containsKey(resolverName)) {
613             throw new IllegalArgumentException JavaDoc("no resolver found called "+resolverName+": check your configuration");
614         }
615     }
616
617     /**
618      * regular expressions as explained in Pattern class may be used in ModuleId
619      * organisation and name
620      *
621      * @param moduleId
622      * @param resolverName
623      * @param branch
624      */

625     public void addModuleConfiguration(ModuleId mid, PatternMatcher matcher, String JavaDoc resolverName, String JavaDoc branch, String JavaDoc conflictManager) {
626         checkResolverName(resolverName);
627         _moduleConfigurations.put(new ModuleIdMatcher(mid, matcher), new ModuleSettings(resolverName, branch, conflictManager));
628     }
629     
630     public File JavaDoc getDefaultIvyUserDir() {
631         if (_defaultUserDir==null) {
632             if (getVariable("ivy.home") != null) {
633                 setDefaultIvyUserDir(new File JavaDoc(getVariable("ivy.home")));
634                 Message.verbose("using ivy.default.ivy.user.dir variable for default ivy user dir: "+_defaultUserDir);
635             } else {
636                 setDefaultIvyUserDir(new File JavaDoc(System.getProperty("user.home"), ".ivy"));
637                 Message.verbose("no default ivy user dir defined: set to "+_defaultUserDir);
638             }
639         }
640         return _defaultUserDir;
641     }
642     
643     public void setDefaultIvyUserDir(File JavaDoc defaultUserDir) {
644         _defaultUserDir = defaultUserDir;
645         setVariable("ivy.default.ivy.user.dir", _defaultUserDir.getAbsolutePath());
646         setVariable("ivy.home", _defaultUserDir.getAbsolutePath());
647     }
648
649     public File JavaDoc getDefaultCache() {
650         if (_defaultCache==null) {
651             _defaultCache = new File JavaDoc(getDefaultIvyUserDir(), "cache");
652             Message.verbose("no default cache defined: set to "+_defaultCache);
653         }
654         return _defaultCache;
655     }
656
657     public DependencyResolver getResolver(ModuleId moduleId) {
658         if (_dictatorResolver != null) {
659             return _dictatorResolver;
660         }
661         String JavaDoc resolverName = getResolverName(moduleId);
662         return getResolver(resolverName);
663     }
664
665     public DependencyResolver getResolver(String JavaDoc resolverName) {
666         if (_dictatorResolver != null) {
667             return _dictatorResolver;
668         }
669         DependencyResolver resolver = (DependencyResolver)_resolversMap.get(resolverName);
670         if (resolver == null) {
671             Message.error("unknown resolver "+resolverName);
672         }
673         return resolver;
674     }
675
676     public DependencyResolver getDefaultResolver() {
677         if (_dictatorResolver != null) {
678             return _dictatorResolver;
679         }
680         if (_defaultResolver == null) {
681             _defaultResolver = (DependencyResolver)_resolversMap.get(_defaultResolverName);
682         }
683         return _defaultResolver;
684     }
685
686     public String JavaDoc getResolverName(ModuleId moduleId) {
687         for (Iterator JavaDoc iter = _moduleConfigurations.keySet().iterator(); iter.hasNext();) {
688             ModuleIdMatcher midm = (ModuleIdMatcher)iter.next();
689             if (midm.matches(moduleId)) {
690                 ModuleSettings ms = (ModuleSettings)_moduleConfigurations.get(midm);
691                 if (ms.getResolverName() != null) {
692                     return ms.getResolverName();
693                 }
694             }
695         }
696         return _defaultResolverName;
697     }
698     
699     public String JavaDoc getDefaultBranch(ModuleId moduleId) {
700         for (Iterator JavaDoc iter = _moduleConfigurations.keySet().iterator(); iter.hasNext();) {
701             ModuleIdMatcher midm = (ModuleIdMatcher)iter.next();
702             if (midm.matches(moduleId)) {
703                 ModuleSettings ms = (ModuleSettings)_moduleConfigurations.get(midm);
704                 if (ms.getBranch() != null) {
705                     return ms.getBranch();
706                 }
707             }
708         }
709         return getDefaultBranch();
710     }
711
712     public String JavaDoc getDefaultBranch() {
713         return _defaultBranch;
714     }
715     public void setDefaultBranch(String JavaDoc defaultBranch) {
716         _defaultBranch = defaultBranch;
717     }
718
719     public ConflictManager getConflictManager(ModuleId moduleId) {
720         for (Iterator JavaDoc iter = _moduleConfigurations.keySet().iterator(); iter.hasNext();) {
721             ModuleIdMatcher midm = (ModuleIdMatcher)iter.next();
722             if (midm.matches(moduleId)) {
723                 ModuleSettings ms = (ModuleSettings)_moduleConfigurations.get(midm);
724                 if (ms.getConflictManager() != null) {
725                     ConflictManager cm = getConflictManager(ms.getConflictManager());
726                     if (cm == null) {
727                         throw new IllegalStateException JavaDoc("ivy badly configured: unknown conflict manager "+ms.getConflictManager());
728                     }
729                     return cm;
730                 }
731             }
732         }
733         return getDefaultConflictManager();
734     }
735
736     public void addConfigured(ConflictManager cm) {
737         addConflictManager(cm.getName(), cm);
738     }
739     
740     public ConflictManager getConflictManager(String JavaDoc name) {
741         if ("default".equals(name)) {
742             return getDefaultConflictManager();
743         }
744         return (ConflictManager)_conflictsManager.get(name);
745     }
746     public void addConflictManager(String JavaDoc name, ConflictManager cm) {
747         if (cm instanceof IvyAware) {
748             ((IvyAware)cm).setIvy(this);
749         }
750         _conflictsManager.put(name, cm);
751     }
752     
753     public void addConfigured(LatestStrategy latest) {
754         addLatestStrategy(latest.getName(), latest);
755     }
756     
757     public LatestStrategy getLatestStrategy(String JavaDoc name) {
758         if ("default".equals(name)) {
759             return getDefaultLatestStrategy();
760         }
761         return (LatestStrategy)_latestStrategies.get(name);
762     }
763     public void addLatestStrategy(String JavaDoc name, LatestStrategy latest) {
764         if (latest instanceof IvyAware) {
765             ((IvyAware)latest).setIvy(this);
766         }
767         _latestStrategies.put(name, latest);
768     }
769     
770     public void addConfigured(Namespace ns) {
771         addNamespace(ns);
772     }
773     
774     public Namespace getNamespace(String JavaDoc name) {
775         if ("system".equals(name)) {
776             return getSystemNamespace();
777         }
778         return (Namespace)_namespaces.get(name);
779     }
780     
781     public Namespace getSystemNamespace() {
782         return Namespace.SYSTEM_NAMESPACE;
783     }
784
785     public void addNamespace(Namespace ns) {
786         if (ns instanceof IvyAware) {
787             ((IvyAware)ns).setIvy(this);
788         }
789         _namespaces.put(ns.getName(), ns);
790     }
791     
792     public void addConfigured(PatternMatcher m) {
793         addMatcher(m);
794     }
795     
796     public PatternMatcher getMatcher(String JavaDoc name) {
797         return (PatternMatcher)_matchers.get(name);
798     }
799     
800     public void addMatcher(PatternMatcher m) {
801         if (m instanceof IvyAware) {
802             ((IvyAware)m).setIvy(this);
803         }
804         _matchers.put(m.getName(), m);
805     }
806     
807     public void addConfigured(ReportOutputter outputter) {
808         addReportOutputter(outputter);
809      }
810      
811      public ReportOutputter getReportOutputter(String JavaDoc name) {
812         return (ReportOutputter) _reportOutputters.get(name);
813      }
814      
815      public void addReportOutputter(ReportOutputter outputter) {
816         if (outputter instanceof IvyAware) {
817             ((IvyAware) outputter).setIvy(this);
818         }
819         _reportOutputters.put(outputter.getName(), outputter);
820      }
821      
822      public ReportOutputter[] getReportOutputters() {
823         return (ReportOutputter[]) _reportOutputters.values().toArray(new ReportOutputter[_reportOutputters.size()]);
824      }
825      
826      public void addConfigured(VersionMatcher vmatcher) {
827          addVersionMatcher(vmatcher);
828       }
829       
830       public VersionMatcher getVersionMatcher(String JavaDoc name) {
831          return (VersionMatcher) _versionMatchers.get(name);
832       }
833       
834       public void addVersionMatcher(VersionMatcher vmatcher) {
835          if (vmatcher instanceof IvyAware) {
836              ((IvyAware) vmatcher).setIvy(this);
837          }
838          _versionMatchers.put(vmatcher.getName(), vmatcher);
839          
840          if (_versionMatcher == null) {
841              _versionMatcher = new ChainVersionMatcher();
842              addVersionMatcher(new ExactVersionMatcher());
843          }
844          if (_versionMatcher instanceof ChainVersionMatcher) {
845             ChainVersionMatcher chain = (ChainVersionMatcher) _versionMatcher;
846             chain.add(vmatcher);
847         }
848       }
849       
850       public VersionMatcher[] getVersionMatchers() {
851          return (VersionMatcher[]) _versionMatchers.values().toArray(new VersionMatcher[_versionMatchers.size()]);
852       }
853
854       public VersionMatcher getVersionMatcher() {
855           if (_versionMatcher == null) {
856               configureDefaultVersionMatcher();
857           }
858           return _versionMatcher;
859       }
860
861       public void configureDefaultVersionMatcher() {
862           addVersionMatcher(new LatestVersionMatcher());
863           addVersionMatcher(new SubVersionMatcher());
864           addVersionMatcher(new VersionRangeMatcher());
865       }
866
867
868     public CircularDependencyStrategy getCircularDependencyStrategy() {
869         if (_circularDependencyStrategy == null) {
870             _circularDependencyStrategy = getCircularDependencyStrategy("default");
871         }
872         return _circularDependencyStrategy;
873     }
874
875     public CircularDependencyStrategy getCircularDependencyStrategy(String JavaDoc name) {
876         if ("default".equals(name)) {
877             name = "warn";
878         }
879         return (CircularDependencyStrategy)_circularDependencyStrategies.get(name);
880     }
881
882     public void setCircularDependencyStrategy(CircularDependencyStrategy strategy) {
883         _circularDependencyStrategy = strategy;
884     }
885     
886     public void addConfigured(CircularDependencyStrategy strategy) {
887         addCircularDependencyStrategy(strategy);
888     }
889
890     private void addCircularDependencyStrategy(CircularDependencyStrategy strategy) {
891         _circularDependencyStrategies.put(strategy.getName(), strategy);
892     }
893     
894     private void configureDefaultCircularDependencyStrategies() {
895         addCircularDependencyStrategy(WarnCircularDependencyStrategy.getInstance());
896         addCircularDependencyStrategy(ErrorCircularDependencyStrategy.getInstance());
897         addCircularDependencyStrategy(IgnoreCircularDependencyStrategy.getInstance());
898     }
899
900     /////////////////////////////////////////////////////////////////////////
901
// CHECK
902
/////////////////////////////////////////////////////////////////////////
903
/**
904      * Checks the given ivy file using current configuration to see if all dependencies
905      * are available, with good confs. If a resolver name is given, it also checks that the declared
906      * publications are available in the corresponding resolver.
907      * Note that the check is not performed recursively, i.e. if a dependency has itself dependencies
908      * badly described or not available, this check will not discover it.
909      */

910     public boolean check(URL JavaDoc ivyFile, String JavaDoc resolvername) {
911         try {
912             IvyContext.getContext().setIvy(this);
913             boolean result = true;
914             // parse ivy file
915
ModuleDescriptor md = ModuleDescriptorParserRegistry.getInstance().parseDescriptor(this, ivyFile, doValidate());
916             
917             // check publications if possible
918
if (resolvername != null) {
919                 DependencyResolver resolver = getResolver(resolvername);
920                 String JavaDoc[] confs = md.getConfigurationsNames();
921                 Set JavaDoc artifacts = new HashSet JavaDoc();
922                 for (int i = 0; i < confs.length; i++) {
923                     artifacts.addAll(Arrays.asList(md.getArtifacts(confs[i])));
924                 }
925                 for (Iterator JavaDoc iter = artifacts.iterator(); iter.hasNext();) {
926                     Artifact art = (Artifact)iter.next();
927                     if (!resolver.exists(art)) {
928                         Message.info("declared publication not found: "+art);
929                         result = false;
930                     }
931                 }
932             }
933             
934             // check dependencies
935
DependencyDescriptor[] dds = md.getDependencies();
936             ResolveData data = new ResolveData(this, getDefaultCache(), new Date JavaDoc(), null, true);
937             for (int i = 0; i < dds.length; i++) {
938                 // check master confs
939
String JavaDoc[] masterConfs = dds[i].getModuleConfigurations();
940                 for (int j = 0; j < masterConfs.length; j++) {
941                     if (!"*".equals(masterConfs[j].trim()) && md.getConfiguration(masterConfs[j]) == null) {
942                         Message.info("dependency required in non existing conf for "+ivyFile+" \n\tin "+dds[i].getDependencyRevisionId()+": "+masterConfs[j]);
943                         result = false;
944                     }
945                 }
946                 // resolve
947
DependencyResolver resolver = getResolver(dds[i].getDependencyId());
948                 ResolvedModuleRevision rmr = resolver.getDependency(dds[i], data);
949                 if (rmr == null) {
950                     Message.info("dependency not found in "+ivyFile+":\n\t"+dds[i]);
951                     result = false;
952                 } else {
953                     String JavaDoc[] depConfs = dds[i].getDependencyConfigurations(md.getConfigurationsNames());
954                     for (int j = 0; j < depConfs.length; j++) {
955                         if (!Arrays.asList(rmr.getDescriptor().getConfigurationsNames()).contains(depConfs[j])) {
956                             Message.info("dependency configuration is missing for "+ivyFile+"\n\tin "+dds[i].getDependencyRevisionId()+": "+depConfs[j]);
957                             result = false;
958                         }
959                         Artifact[] arts = rmr.getDescriptor().getArtifacts(depConfs[j]);
960                         for (int k = 0; k < arts.length; k++) {
961                             if (!resolver.exists(arts[k])) {
962                                 Message.info("dependency artifact is missing for "+ivyFile+"\n\t in "+dds[i].getDependencyRevisionId()+": "+arts[k]);
963                                 result = false;
964                             }
965                         }
966                     }
967                 }
968             }
969             return result;
970         } catch (ParseException JavaDoc e) {
971             Message.info("parse problem on "+ivyFile+": "+e);
972             return false;
973         } catch (IOException JavaDoc e) {
974             Message.info("io problem on "+ivyFile+": "+e);
975             return false;
976         } catch (Exception JavaDoc e) {
977             Message.info("problem on "+ivyFile+": "+e);
978             return false;
979         }
980     }
981     
982
983     public ResolvedModuleRevision findModule(ModuleRevisionId id) {
984         DependencyResolver r = getResolver(id.getModuleId());
985         if (r == null) {
986             throw new IllegalStateException JavaDoc("no resolver found for "+id.getModuleId());
987         }
988         DefaultModuleDescriptor md = DefaultModuleDescriptor.newCallerInstance(id, new String JavaDoc[] {"*"}, false, false);
989         try {
990             return r.getDependency(new DefaultDependencyDescriptor(id, true), new ResolveData(this, getDefaultCache(), null, new ConfigurationResolveReport(this, md, "default", null, getDefaultCache()), false));
991         } catch (ParseException JavaDoc e) {
992             throw new RuntimeException JavaDoc("problem whle parsing repository module descriptor for "+id+": "+e, e);
993         }
994     }
995
996     /////////////////////////////////////////////////////////////////////////
997
// RESOLVE
998
/////////////////////////////////////////////////////////////////////////
999

1000    
1001    public ResolveReport resolve(File JavaDoc ivySource) throws ParseException JavaDoc, IOException JavaDoc {
1002        return resolve(ivySource.toURL());
1003    }
1004    public ResolveReport resolve(URL JavaDoc ivySource) throws ParseException JavaDoc, IOException JavaDoc {
1005        return resolve(ivySource, null, new String JavaDoc[] {"*"}, null, null, true);
1006    }
1007    /**
1008     *
1009     * @param ivySource the url to the descriptor of the module for which dependencies should be resolved
1010     * @param revision the revision of the module for which dependencies should be resolved.
1011     * This revision is considered as the resolved revision of the module, unless it is null.
1012     * If it is null, then a default revision is given if necessary (no revision found in ivy file)
1013     * @param confs the configurations for which dependencies should be resolved
1014     * @param cache the directory where to place resolved dependencies
1015     * @param date the date for which the dependencies should be resolved. All obtained artifacts
1016     * should have a publication date which is before or equal to the given date
1017     * @throws ParseException
1018     * @throws IOException
1019     * @throws NullPointerException if any parameter is null except cache or date
1020     */

1021    public ResolveReport resolve(URL JavaDoc ivySource, String JavaDoc revision, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, boolean validate) throws ParseException JavaDoc, IOException JavaDoc {
1022        return resolve(ivySource, revision, confs, cache, date, validate, false);
1023    }
1024    public ResolveReport resolve(URL JavaDoc ivySource, String JavaDoc revision, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, boolean validate, boolean useCacheOnly) throws ParseException JavaDoc, IOException JavaDoc {
1025        return resolve(ivySource, revision, confs, cache, date, validate, useCacheOnly, FilterHelper.NO_FILTER);
1026    }
1027
1028    /**
1029     * Resolves the module identified by the given mrid with its dependencies.
1030     */

1031    public ResolveReport resolve(ModuleRevisionId mrid, String JavaDoc[] confs) throws ParseException JavaDoc, IOException JavaDoc {
1032        return resolve(mrid, confs, true, false, null, null, true, false, FilterHelper.NO_FILTER);
1033    }
1034
1035    public ResolveReport resolve(final ModuleRevisionId mrid, String JavaDoc[] confs, boolean transitive, boolean changing, File JavaDoc cache, Date JavaDoc date, boolean validate, boolean useCacheOnly, Filter artifactFilter) throws ParseException JavaDoc, IOException JavaDoc {
1036        return resolve(mrid, confs, transitive, changing, cache, date, validate, useCacheOnly, false, artifactFilter);
1037    }
1038
1039    /**
1040     * Resolves the module identified by the given mrid with its dependencies if transitive is set to true.
1041     */

1042    public ResolveReport resolve(final ModuleRevisionId mrid, String JavaDoc[] confs, boolean transitive, boolean changing, File JavaDoc cache, Date JavaDoc date, boolean validate, boolean useCacheOnly, boolean useOrigin, Filter artifactFilter) throws ParseException JavaDoc, IOException JavaDoc {
1043        DefaultModuleDescriptor md;
1044        if (confs.length == 1 && confs[0].equals("*")) {
1045            ResolvedModuleRevision rmr = findModule(mrid);
1046            if (rmr == null) {
1047                md = DefaultModuleDescriptor.newCallerInstance(mrid, confs, transitive, changing);
1048                return new ResolveReport(md){
1049                    public boolean hasError() {
1050                        return true;
1051                    }
1052                    public List JavaDoc getProblemMessages() {
1053                        return Arrays.asList(new String JavaDoc[] {"module not found: "+mrid});
1054                    }
1055                };
1056            } else {
1057                confs = rmr.getDescriptor().getConfigurationsNames();
1058                md = DefaultModuleDescriptor.newCallerInstance(ModuleRevisionId.newInstance(mrid, rmr.getId().getRevision()), confs, transitive, changing);
1059            }
1060        } else {
1061            md = DefaultModuleDescriptor.newCallerInstance(mrid, confs, transitive, changing);
1062        }
1063        
1064        return resolve(md, new String JavaDoc[] {"*"}, cache, date, validate, useCacheOnly, true, useOrigin, true, true, artifactFilter);
1065    }
1066    
1067    public ResolveReport resolve(URL JavaDoc ivySource, String JavaDoc revision, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, boolean validate, boolean useCacheOnly, Filter artifactFilter) throws ParseException JavaDoc, IOException JavaDoc {
1068        return resolve(ivySource, revision, confs, cache, date, validate, useCacheOnly, true, artifactFilter);
1069    }
1070    public ResolveReport resolve(URL JavaDoc ivySource, String JavaDoc revision, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, boolean validate, boolean useCacheOnly, boolean transitive, Filter artifactFilter) throws ParseException JavaDoc, IOException JavaDoc {
1071        return resolve(ivySource, revision, confs, cache, date, validate, useCacheOnly, transitive, false, artifactFilter);
1072    }
1073    /**
1074     * Resolve dependencies of a module described by an ivy file.
1075     *
1076     * Note: the method signature is way too long, we should use a class to store the settings of the resolve.
1077     */

1078    public ResolveReport resolve(URL JavaDoc ivySource, String JavaDoc revision, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, boolean validate, boolean useCacheOnly, boolean transitive, boolean useOrigin, Filter artifactFilter) throws ParseException JavaDoc, IOException JavaDoc {
1079        IvyContext.getContext().setIvy(this);
1080        IvyContext.getContext().setCache(cache);
1081        
1082        URLResource res = new URLResource(ivySource);
1083        ModuleDescriptorParser parser = ModuleDescriptorParserRegistry.getInstance().getParser(res);
1084        Message.verbose("using "+parser+" to parse "+ivySource);
1085        ModuleDescriptor md = parser.parseDescriptor(this, ivySource, validate);
1086        if (revision == null && md.getResolvedModuleRevisionId().getRevision() == null) {
1087            revision = "working@"+getLocalHostName();
1088        }
1089        if (revision != null) {
1090            md.setResolvedModuleRevisionId(ModuleRevisionId.newInstance(md.getModuleRevisionId(), revision));
1091        }
1092
1093        return resolve(md, confs, cache, date, validate, useCacheOnly, transitive, useOrigin, true, true, artifactFilter);
1094    }
1095
1096    public ResolveReport resolve(ModuleDescriptor md, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, boolean validate, boolean useCacheOnly, Filter artifactFilter) throws ParseException JavaDoc, IOException JavaDoc, FileNotFoundException JavaDoc {
1097        return resolve(md, confs, cache, date, validate, useCacheOnly, true, artifactFilter);
1098    }
1099    public ResolveReport resolve(ModuleDescriptor md, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, boolean validate, boolean useCacheOnly, boolean transitive, Filter artifactFilter) throws ParseException JavaDoc, IOException JavaDoc, FileNotFoundException JavaDoc {
1100        return resolve(md, confs, cache, date, validate, useCacheOnly, transitive, true, true, artifactFilter);
1101    }
1102    public ResolveReport resolve(ModuleDescriptor md, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, boolean validate, boolean useCacheOnly, boolean transitive, boolean download, boolean outputReport, Filter artifactFilter) throws ParseException JavaDoc, IOException JavaDoc, FileNotFoundException JavaDoc {
1103        return resolve(md, confs, cache, date, validate, useCacheOnly, transitive, false, download, outputReport, artifactFilter);
1104    }
1105    /**
1106     * Resolve dependencies of a module described by a module descriptor
1107     *
1108     * Note: the method signature is way too long, we should use a class to store the settings of the resolve.
1109     */

1110    public ResolveReport resolve(ModuleDescriptor md, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, boolean validate, boolean useCacheOnly, boolean transitive, boolean useOrigin, boolean download, boolean outputReport, Filter artifactFilter) throws ParseException JavaDoc, IOException JavaDoc, FileNotFoundException JavaDoc {
1111        IvyContext.getContext().setIvy(this);
1112        DependencyResolver oldDictator = getDictatorResolver();
1113        if (useCacheOnly) {
1114            setDictatorResolver(new CacheResolver(this));
1115        }
1116        try {
1117            if (cache==null) { // ensure that a cache exists
1118
cache = getDefaultCache();
1119                IvyContext.getContext().setCache(cache);
1120            }
1121            if (artifactFilter == null) {
1122                artifactFilter = FilterHelper.NO_FILTER;
1123            }
1124            if (confs.length == 1 && confs[0].equals("*")) {
1125                confs = md.getConfigurationsNames();
1126            }
1127            fireIvyEvent(new StartResolveEvent(this, md, confs));
1128            
1129            long start = System.currentTimeMillis();
1130            Message.info(":: resolving dependencies :: "+md.getResolvedModuleRevisionId()+(transitive?"":" [not transitive]"));
1131            Message.info("\tconfs: "+Arrays.asList(confs));
1132            Message.verbose("\tvalidate = "+validate);
1133            ResolveReport report = new ResolveReport(md);
1134
1135            // resolve dependencies
1136
IvyNode[] dependencies = getDependencies(md, confs, cache, date, report, validate, transitive);
1137            report.setDependencies(Arrays.asList(dependencies), artifactFilter);
1138
1139            
1140            // produce resolved ivy file and ivy properties in cache
1141
File JavaDoc ivyFileInCache = getResolvedIvyFileInCache(cache, md.getResolvedModuleRevisionId());
1142            md.toIvyFile(ivyFileInCache);
1143
1144            // we store the resolved dependencies revisions and statuses per asked dependency revision id,
1145
// for direct dependencies only.
1146
// this is used by the deliver task to resolve dynamic revisions to static ones
1147
File JavaDoc ivyPropertiesInCache = getResolvedIvyPropertiesInCache(cache, md.getResolvedModuleRevisionId());
1148            Properties JavaDoc props = new Properties JavaDoc();
1149            if (dependencies.length > 0) {
1150                IvyNode root = dependencies[0].getRoot();
1151                for (int i = 0; i < dependencies.length; i++) {
1152                    if (!dependencies[i].isCompletelyEvicted() && !dependencies[i].hasProblem()) {
1153                        DependencyDescriptor dd = dependencies[i].getDependencyDescriptor(root);
1154                        if (dd != null) {
1155                            String JavaDoc rev = dependencies[i].getResolvedId().getRevision();
1156                            String JavaDoc status = dependencies[i].getDescriptor().getStatus();
1157                            props.put(dd.getDependencyRevisionId().encodeToString(), rev+" "+status);
1158                        }
1159                    }
1160                }
1161            }
1162            props.store(new FileOutputStream JavaDoc(ivyPropertiesInCache), md.getResolvedModuleRevisionId()+ " resolved revisions");
1163            Message.verbose("\tresolved ivy file produced in "+ivyFileInCache);
1164            
1165            report.setResolveTime(System.currentTimeMillis()-start);
1166
1167            if (download) {
1168                Message.verbose(":: downloading artifacts ::");
1169    
1170                downloadArtifacts(report, cache, useOrigin, artifactFilter);
1171            }
1172            
1173            
1174            if (outputReport) {
1175                outputReport(report, cache);
1176            }
1177            
1178            fireIvyEvent(new EndResolveEvent(this, md, confs, report));
1179            return report;
1180        } finally {
1181            setDictatorResolver(oldDictator);
1182        }
1183    }
1184
1185    public void outputReport(ResolveReport report, File JavaDoc cache) {
1186        Message.info(":: resolution report ::");
1187        report.setProblemMessages(Message.getProblems());
1188        // output report
1189
report.output(getReportOutputters(), cache);
1190        
1191        Message.verbose("\tresolve done ("+report.getResolveTime()+"ms resolve - "+report.getDownloadTime()+"ms download)");
1192        Message.sumupProblems();
1193    }
1194
1195    public void downloadArtifacts(ResolveReport report, File JavaDoc cache, boolean useOrigin, Filter artifactFilter) {
1196        long start = System.currentTimeMillis();
1197        IvyNode[] dependencies = (IvyNode[]) report.getDependencies().toArray(new IvyNode[report.getDependencies().size()]);
1198        
1199        fireIvyEvent(new PrepareDownloadEvent(this, (Artifact[])report.getArtifacts().toArray(new Artifact[report.getArtifacts().size()])));
1200        
1201        for (int i = 0; i < dependencies.length; i++) {
1202            checkInterrupted();
1203            //download artifacts required in all asked configurations
1204
if (!dependencies[i].isCompletelyEvicted() && !dependencies[i].hasProblem()) {
1205                DependencyResolver resolver = dependencies[i].getModuleRevision().getArtifactResolver();
1206                Artifact[] selectedArtifacts = dependencies[i].getSelectedArtifacts(artifactFilter);
1207                DownloadReport dReport = resolver.download(selectedArtifacts, this, cache, useOrigin);
1208                ArtifactDownloadReport[] adrs = dReport.getArtifactsReports();
1209                for (int j = 0; j < adrs.length; j++) {
1210                    if (adrs[j].getDownloadStatus() == DownloadStatus.FAILED) {
1211                        Message.warn("\t[NOT FOUND ] "+adrs[j].getArtifact());
1212                        resolver.reportFailure(adrs[j].getArtifact());
1213                    }
1214                }
1215                // update concerned reports
1216
String JavaDoc[] dconfs = dependencies[i].getRootModuleConfigurations();
1217                for (int j = 0; j < dconfs.length; j++) {
1218                    // the report itself is responsible to take into account only
1219
// artifacts required in its corresponding configuration
1220
// (as described by the Dependency object)
1221
if (dependencies[i].isEvicted(dconfs[j])) {
1222                        report.getConfigurationReport(dconfs[j]).addDependency(dependencies[i]);
1223                    } else {
1224                        report.getConfigurationReport(dconfs[j]).addDependency(dependencies[i], dReport);
1225                    }
1226                }
1227            }
1228        }
1229        report.setDownloadTime(System.currentTimeMillis() - start);
1230    }
1231
1232    /**
1233     * Check if the current operation has been interrupted, and if it is the case, throw a runtime exception
1234     */

1235    public void checkInterrupted() {
1236        if (isInterrupted()) {
1237            Message.info("operation interrupted");
1238            throw new RuntimeException JavaDoc("operation interrupted");
1239        }
1240    }
1241    
1242    /**
1243     * Download an artifact to the cache.
1244     * Not used internally, useful especially for IDE plugins
1245     * needing to download artifact one by one (for source or javadoc artifact,
1246     * for instance).
1247     *
1248     * Downloaded artifact file can be accessed using getArchiveFileInCache method.
1249     *
1250     * It is possible to track the progression of the download using classical ivy
1251     * progress monitoring feature (see addTransferListener).
1252     *
1253     * @param artifact the artifact to download
1254     * @param cache the cache to use. If null, will use default cache
1255     * @return a report concerning the download
1256     */

1257    public ArtifactDownloadReport download(Artifact artifact, File JavaDoc cache) {
1258        IvyContext.getContext().setIvy(this);
1259        IvyContext.getContext().setCache(cache);
1260        if (cache == null) {
1261            cache = getDefaultCache();
1262        }
1263        DependencyResolver resolver = getResolver(artifact.getModuleRevisionId().getModuleId());
1264        DownloadReport r = resolver.download(new Artifact[] {artifact}, this, cache, false);
1265        return r.getArtifactReport(artifact);
1266    }
1267    
1268    /**
1269     * Resolve the dependencies of a module without downloading corresponding artifacts.
1270     * The module to resolve is given by its ivy file URL. This method requires
1271     * appropriate configuration of the ivy instance, especially resolvers.
1272     *
1273     * @param ivySource url of the ivy file to use for dependency resolving
1274     * @param confs an array of configuration names to resolve - must not be null nor empty
1275     * @param cache the cache to use - default cache is used if null
1276     * @param date the date to which resolution must be done - may be null
1277     * @return an array of the resolved dependencies
1278     * @throws ParseException if a parsing problem occured in the ivy file
1279     * @throws IOException if an IO problem was raised during ivy file parsing
1280     */

1281    public IvyNode[] getDependencies(URL JavaDoc ivySource, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, boolean validate) throws ParseException JavaDoc, IOException JavaDoc {
1282        return getDependencies(ModuleDescriptorParserRegistry.getInstance().parseDescriptor(this, ivySource, validate), confs, cache, date, null, validate);
1283    }
1284    
1285    /**
1286     * Resolve the dependencies of a module without downloading corresponding artifacts.
1287     * The module to resolve is given by its module descriptor.This method requires
1288     * appropriate configuration of the ivy instance, especially resolvers.
1289     *
1290     * @param md the descriptor of the module for which we want to get dependencies - must not be null
1291     * @param confs an array of configuration names to resolve - must not be null nor empty
1292     * @param cache the cache to use - default cache is used if null
1293     * @param date the date to which resolution must be done - may be null
1294     * @param report a resolve report to fill during resolution - may be null
1295     * @return an array of the resolved Dependencies
1296     */

1297    public IvyNode[] getDependencies(ModuleDescriptor md, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, ResolveReport report, boolean validate) {
1298        return getDependencies(md, confs, cache, date, report, validate, true);
1299    }
1300    public IvyNode[] getDependencies(ModuleDescriptor md, String JavaDoc[] confs, File JavaDoc cache, Date JavaDoc date, ResolveReport report, boolean validate, boolean transitive) {
1301        IvyContext.getContext().setIvy(this);
1302        IvyContext.getContext().setCache(cache);
1303        if (md == null) {
1304            throw new NullPointerException JavaDoc("module descriptor must not be null");
1305        }
1306        if (cache==null) { // ensure that a cache exists
1307
cache = getDefaultCache();
1308        }
1309        if (confs.length == 1 && confs[0].equals("*")) {
1310            confs = md.getConfigurationsNames();
1311        }
1312        
1313        Map JavaDoc dependenciesMap = new LinkedHashMap JavaDoc();
1314        Date JavaDoc reportDate = new Date JavaDoc();
1315        ResolveData data = new ResolveData(this, cache, date, null, validate, transitive, dependenciesMap);
1316        IvyNode rootNode = new IvyNode(data, md);
1317        
1318        for (int i = 0; i < confs.length; i++) {
1319            // for each configuration we clear the cache of what's been fetched
1320
_fetchedSet.clear();
1321            
1322            Configuration configuration = md.getConfiguration(confs[i]);
1323            if (configuration == null) {
1324                Message.error("asked configuration not found in "+md.getModuleRevisionId()+": "+confs[i]);
1325            } else {
1326                ConfigurationResolveReport confReport = null;
1327                if (report != null) {
1328                    confReport = report.getConfigurationReport(confs[i]);
1329                    if (confReport == null) {
1330                        confReport = new ConfigurationResolveReport(this, md, confs[i], reportDate, cache);
1331                        report.addReport(confs[i], confReport);
1332                    }
1333                }
1334                // we reuse the same resolve data with a new report for each conf
1335
data.setReport(confReport);
1336                
1337                // update the root module conf we are about to fetch
1338
rootNode.setRootModuleConf(confs[i]);
1339                rootNode.setRequestedConf(confs[i]);
1340                rootNode.updateConfsToFetch(Collections.singleton(confs[i]));
1341                
1342                // go fetch !
1343
fetchDependencies(rootNode, confs[i], false);
1344            }
1345        }
1346        
1347        // prune and reverse sort fectched dependencies
1348
Collection JavaDoc dependencies = new LinkedHashSet JavaDoc(dependenciesMap.size()); // use a Set to avoids duplicates
1349
for (Iterator JavaDoc iter = dependenciesMap.values().iterator(); iter.hasNext();) {
1350            IvyNode dep = (IvyNode) iter.next();
1351            if (dep != null) {
1352                dependencies.add(dep);
1353            }
1354        }
1355        List JavaDoc sortedDependencies = sortNodes(dependencies);
1356        Collections.reverse(sortedDependencies);
1357
1358        // handle transitive eviction now:
1359
// if a module has been evicted then all its dependencies required
1360
// only by it should be evicted too. Since nodes are now sorted from the more dependent to
1361
// the less one, we can traverse the list and check only the direct parent and not all
1362
// the ancestors
1363
for (ListIterator JavaDoc iter = sortedDependencies.listIterator(); iter.hasNext();) {
1364            IvyNode node = (IvyNode)iter.next();
1365            if (!node.isCompletelyEvicted()) {
1366                for (int i = 0; i < confs.length; i++) {
1367                    IvyNode.Caller[] callers = node.getCallers(confs[i]);
1368                    if (debugConflictResolution()) {
1369                        Message.debug("checking if "+node.getId()+" is transitively evicted in "+confs[i]);
1370                    }
1371                    boolean allEvicted = callers.length > 0;
1372                    for (int j = 0; j < callers.length; j++) {
1373                        if (callers[j].getModuleRevisionId().equals(md.getModuleRevisionId())) {
1374                            // the caller is the root module itself, it can't be evicted
1375
allEvicted = false;
1376                            break;
1377                        } else {
1378                            IvyNode callerNode = (IvyNode)dependenciesMap.get(callers[j].getModuleRevisionId());
1379                            if (callerNode == null) {
1380                                Message.warn("ivy internal error: no node found for "+callers[j].getModuleRevisionId()+": looked in "+dependenciesMap.keySet()+" and root module id was "+md.getModuleRevisionId());
1381                            } else if (!callerNode.isEvicted(confs[i])) {
1382                                allEvicted = false;
1383                                break;
1384                            } else {
1385                                if (debugConflictResolution()) {
1386                                    Message.debug("caller "+callerNode.getId()+" of "+node.getId()+" is evicted");
1387                                }
1388                            }
1389                        }
1390                    }
1391                    if (allEvicted) {
1392                        Message.verbose("all callers are evicted for "+node+": evicting too");
1393                        node.markEvicted(confs[i], null, null, null);
1394                    } else {
1395                        if (debugConflictResolution()) {
1396                            Message.debug(node.getId()+" isn't transitively evicted, at least one caller was not evicted");
1397                        }
1398                    }
1399                }
1400            }
1401        }
1402        
1403        return (IvyNode[]) dependencies.toArray(new IvyNode[dependencies.size()]);
1404    }
1405
1406
1407    
1408    
1409    private void fetchDependencies(IvyNode node, String JavaDoc conf, boolean shouldBePublic) {
1410        checkInterrupted();
1411        long start = System.currentTimeMillis();
1412        if (debugConflictResolution()) {
1413            Message.debug(node.getId()+" => resolving dependencies in "+conf);
1414        }
1415        resolveConflict(node, node.getParent());
1416        
1417        if (node.loadData(conf, shouldBePublic)) {
1418            node = node.getRealNode(true); // if data loading discarded the node, get the real one
1419

1420            resolveConflict(node, node.getParent());
1421            if (!node.isEvicted(node.getRootModuleConf())) {
1422                String JavaDoc[] confs = node.getRealConfs(conf);
1423                for (int i = 0; i < confs.length; i++) {
1424                    doFetchDependencies(node, confs[i]);
1425                }
1426            }
1427        } else if (!node.hasProblem()) {
1428            // the node has not been loaded but hasn't problem: it was already loaded
1429
// => we just have to update its dependencies data
1430
if (!node.isEvicted(node.getRootModuleConf())) {
1431                String JavaDoc[] confs = node.getRealConfs(conf);
1432                for (int i = 0; i < confs.length; i++) {
1433                    doFetchDependencies(node, confs[i]);
1434                }
1435            }
1436        }
1437        if (node.isEvicted(node.getRootModuleConf())) {
1438            // update selected nodes with confs asked in evicted one
1439
IvyNode.EvictionData ed = node.getEvictedData(node.getRootModuleConf());
1440            if (ed.getSelected() != null) {
1441                for (Iterator JavaDoc iter = ed.getSelected().iterator(); iter.hasNext();) {
1442                    IvyNode selected = (IvyNode)iter.next();
1443                    fetchDependencies(selected, conf, true);
1444                }
1445            }
1446        }
1447        if (debugConflictResolution()) {
1448            Message.debug(node.getId()+" => dependencies resolved in "+conf+" ("+(System.currentTimeMillis()-start)+"ms)");
1449        }
1450    }
1451
1452    private void doFetchDependencies(IvyNode node, String JavaDoc conf) {
1453        Configuration c = node.getConfiguration(conf);
1454        if (c == null) {
1455            Message.warn("configuration not found '"+conf+"' in "+node.getResolvedId()+": ignoring");
1456            if (node.getParent() != null) {
1457                Message.warn("it was required from "+node.getParent().getResolvedId());
1458            }
1459            return;
1460        }
1461        // we handle the case where the asked configuration extends others:
1462
// we have to first fetch the extended configurations
1463

1464        // first we check if this is the actual requested conf (not an extended one)
1465
boolean requestedConfSet = false;
1466        if (node.getRequestedConf()==null) {
1467            node.setRequestedConf(conf);
1468            requestedConfSet = true;
1469        }
1470        // now let's recurse in extended confs
1471
String JavaDoc[] extendedConfs = c.getExtends();
1472        if (extendedConfs.length > 0) {
1473            node.updateConfsToFetch(Arrays.asList(extendedConfs));
1474        }
1475        for (int i = 0; i < extendedConfs.length; i++) {
1476            fetchDependencies(node, extendedConfs[i], false);
1477        }
1478        
1479        // now we can actually resolve this configuration dependencies
1480
DependencyDescriptor dd = node.getDependencyDescriptor(node.getParent());
1481        if (!isDependenciesFetched(node, conf) && (dd == null || node.isTransitive())) {
1482            Collection JavaDoc dependencies = node.getDependencies(conf, true);
1483            for (Iterator JavaDoc iter = dependencies.iterator(); iter.hasNext();) {
1484                IvyNode dep = (IvyNode)iter.next();
1485                dep = dep.getRealNode(); // the node may have been resolved to another real one while resolving other deps
1486
node.traverse(conf, dep); // dependency traversal data may have been changed while resolving other deps, we update it
1487
if (dep.isCircular()) {
1488                    continue;
1489                }
1490                String JavaDoc[] confs = dep.getRequiredConfigurations(node, conf);
1491                for (int i = 0; i < confs.length; i++) {
1492                    fetchDependencies(dep, confs[i], true);
1493                }
1494                // if there are still confs to fetch (usually because they have
1495
// been updated when evicting another module), we fetch them now
1496
confs = dep.getConfsToFetch();
1497                for (int i = 0; i < confs.length; i++) {
1498                    fetchDependencies(dep, confs[i], true);
1499                }
1500            }
1501        }
1502        // we have finiched with this configuration, if it was the original requested conf
1503
// we can clean it now
1504
if (requestedConfSet) {
1505            node.setRequestedConf(null);
1506        }
1507        
1508    }
1509
1510
1511    /**
1512     * Returns true if we've already fetched the dependencies for this node and configuration
1513     * @param node node to check
1514     * @param conf configuration to check
1515     * @return true if we've already fetched this dependency
1516     */

1517    private boolean isDependenciesFetched(IvyNode node, String JavaDoc conf) {
1518        ModuleId moduleId = node.getModuleId();
1519        ModuleRevisionId moduleRevisionId = node.getResolvedId();
1520        String JavaDoc key = moduleId.getOrganisation()+"|"+moduleId.getName()+"|"+moduleRevisionId.getRevision() +
1521            "|" + conf;
1522        if (_fetchedSet.contains(key)) {
1523            return true;
1524        }
1525        _fetchedSet.add(key);
1526        return false;
1527    }
1528
1529    private void resolveConflict(IvyNode node, IvyNode parent) {
1530        resolveConflict(node, parent, Collections.EMPTY_SET);
1531    }
1532    private void resolveConflict(IvyNode node, IvyNode parent, Collection JavaDoc toevict) {
1533        if (parent == null || node == parent) {
1534            return;
1535        }
1536        // check if job is not already done
1537
if (checkConflictSolved(node, parent)) {
1538            return;
1539        }
1540        
1541        // compute conflicts
1542
Collection JavaDoc resolvedNodes = new HashSet JavaDoc(parent.getResolvedNodes(node.getModuleId(), node.getRootModuleConf()));
1543        Collection JavaDoc conflicts = computeConflicts(node, parent, toevict, resolvedNodes);
1544        if (debugConflictResolution()) {
1545            Message.debug("found conflicting revisions for "+node+" in "+parent+": "+conflicts);
1546        }
1547        
1548        Collection JavaDoc resolved = parent.getConflictManager(node.getModuleId()).resolveConflicts(parent, conflicts);
1549        if (debugConflictResolution()) {
1550            Message.debug("selected revisions for "+node+" in "+parent+": "+resolved);
1551        }
1552        if (resolved.contains(node)) {
1553            // node has been selected for the current parent
1554

1555            // handle previously selected nodes that are now evicted by this new node
1556
toevict = resolvedNodes;
1557            toevict.removeAll(resolved);
1558            
1559            for (Iterator JavaDoc iter = toevict.iterator(); iter.hasNext();) {
1560                IvyNode te = (IvyNode)iter.next();
1561                te.markEvicted(node.getRootModuleConf(), parent, parent.getConflictManager(node.getModuleId()), resolved);
1562                
1563                if (debugConflictResolution()) {
1564                    Message.debug("evicting "+te+" by "+te.getEvictedData(node.getRootModuleConf()));
1565                }
1566            }
1567            
1568            // it's very important to update resolved and evicted nodes BEFORE recompute parent call
1569
// to allow it to recompute its resolved collection with correct data
1570
// if necessary
1571
parent.setResolvedNodes(node.getModuleId(), node.getRootModuleConf(), resolved);
1572
1573            Collection JavaDoc evicted = new HashSet JavaDoc(parent.getEvictedNodes(node.getModuleId(), node.getRootModuleConf()));
1574            evicted.removeAll(resolved);
1575            evicted.addAll(toevict);
1576            parent.setEvictedNodes(node.getModuleId(), node.getRootModuleConf(), evicted);
1577            
1578            resolveConflict(node, parent.getParent(), toevict);
1579        } else {
1580            // node has been evicted for the current parent
1581
if (resolved.isEmpty()) {
1582                if (debugConflictResolution()) {
1583                    Message.verbose("conflict manager '"+parent.getConflictManager(node.getModuleId())+"' evicted all revisions among "+conflicts);
1584                }
1585            }
1586            
1587            
1588            // it's time to update parent resolved and evicted with what was found
1589

1590            Collection JavaDoc evicted = new HashSet JavaDoc(parent.getEvictedNodes(node.getModuleId(), node.getRootModuleConf()));
1591            toevict.removeAll(resolved);
1592            evicted.removeAll(resolved);
1593            evicted.addAll(toevict);
1594            evicted.add(node);
1595            parent.setEvictedNodes(node.getModuleId(), node.getRootModuleConf(), evicted);
1596
1597            
1598            node.markEvicted(node.getRootModuleConf(), parent, parent.getConflictManager(node.getModuleId()), resolved);
1599            if (debugConflictResolution()) {
1600                Message.debug("evicting "+node+" by "+node.getEvictedData(node.getRootModuleConf()));
1601            }
1602
1603            // if resolved changed we have to go up in the graph
1604
Collection JavaDoc prevResolved = parent.getResolvedNodes(node.getModuleId(), node.getRootModuleConf());
1605            if (!prevResolved.equals(resolved)) {
1606                parent.setResolvedNodes(node.getModuleId(), node.getRootModuleConf(), resolved);
1607                for (Iterator JavaDoc iter = resolved.iterator(); iter.hasNext();) {
1608                    IvyNode sel = (IvyNode)iter.next();
1609                    if (!prevResolved.contains(sel)) {
1610                        resolveConflict(sel, parent.getParent(), toevict);
1611                    }
1612                }
1613            }
1614
1615        }
1616    }
1617
1618    private Collection JavaDoc computeConflicts(IvyNode node, IvyNode parent, Collection JavaDoc toevict, Collection JavaDoc resolvedNodes) {
1619        Collection JavaDoc conflicts = new HashSet JavaDoc();
1620        if (resolvedNodes.removeAll(toevict)) {
1621            // parent.resolved(node.mid) is not up to date:
1622
// recompute resolved from all sub nodes
1623
conflicts.add(node);
1624            Collection JavaDoc deps = parent.getDependencies(parent.getRequiredConfigurations());
1625            for (Iterator JavaDoc iter = deps.iterator(); iter.hasNext();) {
1626                IvyNode dep = (IvyNode)iter.next();
1627                conflicts.addAll(dep.getResolvedNodes(node.getModuleId(), node.getRootModuleConf()));
1628            }
1629        } else if (resolvedNodes.isEmpty() && node.getParent() != parent) {
1630            conflicts.add(node);
1631            DependencyDescriptor[] dds = parent.getDescriptor().getDependencies();
1632            for (int i = 0; i < dds.length; i++) {
1633                if (dds[i].getDependencyId().equals(node.getModuleId())) {
1634                    IvyNode n = node.findNode(dds[i].getDependencyRevisionId());
1635                    if (n != null) {
1636                        conflicts.add(n);
1637                        break;
1638                    }
1639                }
1640            }
1641        } else {
1642            conflicts.add(node);
1643            conflicts.addAll(resolvedNodes);
1644        }
1645        return conflicts;
1646    }
1647
1648    private boolean checkConflictSolved(IvyNode node, IvyNode parent) {
1649        if (parent.getResolvedRevisions(node.getModuleId(), node.getRootModuleConf()).contains(node.getResolvedId())) {
1650            // resolve conflict has already be done with node with the same id
1651
// => job already done, we just have to check if the node wasn't previously evicted in root ancestor
1652
if (debugConflictResolution()) {
1653                Message.debug("conflict resolution already done for "+node+" in "+parent);
1654            }
1655            EvictionData evictionData = node.getEvictionDataInRoot(node.getRootModuleConf(), parent);
1656            if (evictionData != null) {
1657                // node has been previously evicted in an ancestor: we mark it as evicted
1658
if (debugConflictResolution()) {
1659                    Message.debug(node+" was previously evicted in root module conf "+node.getRootModuleConf());
1660                }
1661
1662                node.markEvicted(evictionData);
1663                if (debugConflictResolution()) {
1664                    Message.debug("evicting "+node+" by "+evictionData);
1665                }
1666            }
1667            return true;
1668        } else if (parent.getEvictedRevisions(node.getModuleId(), node.getRootModuleConf()).contains(node.getResolvedId())) {
1669            // resolve conflict has already be done with node with the same id
1670
// => job already done, we just have to check if the node wasn't previously selected in root ancestor
1671
if (debugConflictResolution()) {
1672                Message.debug("conflict resolution already done for "+node+" in "+parent);
1673            }
1674            return true;
1675        }
1676        return false;
1677    }
1678
1679    public ResolvedModuleRevision findModuleInCache(ModuleRevisionId mrid, File JavaDoc cache, boolean validate) {
1680        IvyContext.getContext().setIvy(this);
1681        IvyContext.getContext().setCache(cache);
1682        // first, check if it is in cache
1683
if (!getVersionMatcher().isDynamic(mrid)) {
1684            File JavaDoc ivyFile = getIvyFileInCache(cache, mrid);
1685            if (ivyFile.exists()) {
1686                // found in cache !
1687
try {
1688                    ModuleDescriptor depMD = XmlModuleDescriptorParser.getInstance().parseDescriptor(this, ivyFile.toURL(), validate);
1689                    String JavaDoc resolverName = getSavedResolverName(cache, depMD);
1690                    String JavaDoc artResolverName = getSavedArtResolverName(cache, depMD);
1691                    DependencyResolver resolver = (DependencyResolver)_resolversMap.get(resolverName);
1692                    if (resolver == null) {
1693                        Message.debug("\tresolver not found: "+resolverName+" => trying to use the one configured for "+mrid);
1694                        resolver = getResolver(depMD.getResolvedModuleRevisionId().getModuleId());
1695                        if (resolver != null) {
1696                            Message.debug("\tconfigured resolver found for "+depMD.getResolvedModuleRevisionId()+": "+resolver.getName()+": saving this data");
1697                            saveResolver(cache, depMD, resolver.getName());
1698                        }
1699                    }
1700                    DependencyResolver artResolver = (DependencyResolver)_resolversMap.get(artResolverName);
1701                    if (artResolver == null) {
1702                        artResolver = resolver;
1703                    }
1704                    if (resolver != null) {
1705                        Message.debug("\tfound ivy file in cache for "+mrid+" (resolved by "+resolver.getName()+"): "+ivyFile);
1706                        return new DefaultModuleRevision(resolver, artResolver, depMD, false, false, ivyFile.toURL());
1707                    } else {
1708                        Message.debug("\tresolver not found: "+resolverName+" => cannot use cached ivy file for "+mrid);
1709                    }
1710                } catch (Exception JavaDoc e) {
1711                    // will try with resolver
1712
Message.debug("\tproblem while parsing cached ivy file for: "+mrid+": "+e.getMessage());
1713                }
1714            } else {
1715                Message.debug("\tno ivy file in cache for "+mrid+": tried "+ivyFile);
1716            }
1717        }
1718        return null;
1719    }
1720
1721
1722    /////////////////////////////////////////////////////////////////////////
1723
// INSTALL
1724
/////////////////////////////////////////////////////////////////////////
1725

1726    public ResolveReport install(ModuleRevisionId mrid, String JavaDoc from, String JavaDoc to, boolean transitive, boolean validate, boolean overwrite, Filter artifactFilter, File JavaDoc cache, String JavaDoc matcherName) throws IOException JavaDoc {
1727        IvyContext.getContext().setIvy(this);
1728        IvyContext.getContext().setCache(cache);
1729        if (cache == null) {
1730            cache = getDefaultCache();
1731        }
1732        if (artifactFilter == null) {
1733            artifactFilter = FilterHelper.NO_FILTER;
1734        }
1735        DependencyResolver fromResolver = getResolver(from);
1736        DependencyResolver toResolver = getResolver(to);
1737        if (fromResolver == null) {
1738            throw new IllegalArgumentException JavaDoc("unknown resolver "+from+". Available resolvers are: "+_resolversMap.keySet());
1739        }
1740        if (toResolver == null) {
1741            throw new IllegalArgumentException JavaDoc("unknown resolver "+to+". Available resolvers are: "+_resolversMap.keySet());
1742        }
1743        PatternMatcher matcher = getMatcher(matcherName);
1744        if (matcher == null) {
1745            throw new IllegalArgumentException JavaDoc("unknown matcher "+matcherName+". Available matchers are: "+_matchers.keySet());
1746        }
1747        
1748        // build module file declaring the dependency
1749
Message.info(":: installing "+mrid+" ::");
1750        DependencyResolver oldDicator = getDictatorResolver();
1751        boolean log = logNotConvertedExclusionRule();
1752        try {
1753            setLogNotConvertedExclusionRule(true);
1754            setDictatorResolver(fromResolver);
1755            
1756            DefaultModuleDescriptor md = new DefaultModuleDescriptor(ModuleRevisionId.newInstance("jayasoft", "ivy-install", "1.0"), getStatusManager().getDefaultStatus(), new Date JavaDoc());
1757            md.addConfiguration(new Configuration("default"));
1758            md.addConflictManager(new ModuleId(ExactPatternMatcher.ANY_EXPRESSION, ExactPatternMatcher.ANY_EXPRESSION), ExactPatternMatcher.getInstance(), new NoConflictManager());
1759            
1760            if (MatcherHelper.isExact(matcher, mrid)) {
1761                DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(md, mrid, false, false, transitive);
1762                dd.addDependencyConfiguration("default", "*");
1763                md.addDependency(dd);
1764            } else {
1765                Collection JavaDoc mrids = findModuleRevisionIds(fromResolver, mrid, matcher);
1766                                
1767                for (Iterator JavaDoc iter = mrids.iterator(); iter.hasNext();) {
1768                    ModuleRevisionId foundMrid = (ModuleRevisionId)iter.next();
1769                    Message.info("\tfound "+foundMrid+" to install: adding to the list");
1770                    DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(md, foundMrid, false, false, transitive);
1771                    dd.addDependencyConfiguration("default", "*");
1772                    md.addDependency(dd);
1773                }
1774            }
1775            
1776            // resolve using appropriate resolver
1777
ResolveReport report = new ResolveReport(md);
1778            
1779            Message.info(":: resolving dependencies ::");
1780            IvyNode[] dependencies = getDependencies(md, new String JavaDoc[] {"default"}, cache, null, report, validate);
1781            report.setDependencies(Arrays.asList(dependencies), artifactFilter);
1782            
1783            Message.info(":: downloading artifacts to cache ::");
1784            downloadArtifacts(report, cache, false, artifactFilter);
1785
1786            // now that everything is in cache, we can publish all these modules
1787
Message.info(":: installing in "+to+" ::");
1788            for (int i = 0; i < dependencies.length; i++) {
1789                ModuleDescriptor depmd = dependencies[i].getDescriptor();
1790                if (depmd != null) {
1791                    Message.verbose("installing "+depmd.getModuleRevisionId());
1792                    publish(depmd,
1793                            toResolver,
1794                            Collections.singleton(cache.getAbsolutePath()+"/"+getCacheArtifactPattern()),
1795                            cache.getAbsolutePath()+"/"+getCacheIvyPattern(),
1796                            null,
1797                            overwrite,
1798                            null);
1799                }
1800            }
1801
1802            Message.info(":: install resolution report ::");
1803            
1804            // output report
1805
report.output(getReportOutputters(), cache);
1806
1807            return report;
1808        } finally {
1809            setDictatorResolver(oldDicator);
1810            setLogNotConvertedExclusionRule(log);
1811        }
1812    }
1813
1814    public Collection JavaDoc findModuleRevisionIds(DependencyResolver resolver, ModuleRevisionId pattern, PatternMatcher matcher) {
1815        IvyContext.getContext().setIvy(this);
1816        Collection JavaDoc mrids = new ArrayList JavaDoc();
1817        String JavaDoc resolverName = resolver.getName();
1818        
1819        Message.verbose("looking for modules matching "+pattern+" using "+matcher.getName());
1820        Namespace fromNamespace = resolver instanceof AbstractResolver ? ((AbstractResolver)resolver).getNamespace() : null;
1821        
1822        Collection JavaDoc modules = new ArrayList JavaDoc();
1823        
1824        OrganisationEntry[] orgs = resolver.listOrganisations();
1825        if (orgs == null || orgs.length == 0) {
1826            // hack for resolvers which are not able to list organisation, we try to see if the asked organisation is not an exact one:
1827
String JavaDoc org = pattern.getOrganisation();
1828            if (fromNamespace != null) {
1829                org = NameSpaceHelper.transform(pattern.getModuleId(), fromNamespace.getFromSystemTransformer()).getOrganisation();
1830            }
1831            modules.addAll(Arrays.asList(resolver.listModules(new OrganisationEntry(resolver, org))));
1832        } else {
1833            Matcher orgMatcher = matcher.getMatcher(pattern.getOrganisation());
1834            for (int i = 0; i < orgs.length; i++) {
1835                String JavaDoc org = orgs[i].getOrganisation();
1836                String JavaDoc systemOrg = org;
1837                if (fromNamespace != null) {
1838                    systemOrg = NameSpaceHelper.transformOrganisation(org, fromNamespace.getToSystemTransformer());
1839                }
1840                if (orgMatcher.matches(systemOrg)) {
1841                    modules.addAll(Arrays.asList(resolver.listModules(new OrganisationEntry(resolver, org))));
1842                }
1843            }
1844        }
1845        Message.debug("found " + modules.size() + " modules for "+pattern.getOrganisation()+" on " + resolverName);
1846        boolean foundModule = false;
1847        for (Iterator JavaDoc iter = modules.iterator(); iter.hasNext();) {
1848            ModuleEntry mEntry = (ModuleEntry)iter.next();
1849            
1850            ModuleId foundMid = new ModuleId(mEntry.getOrganisation(), mEntry.getModule());
1851            ModuleId systemMid = foundMid;
1852            if (fromNamespace != null) {
1853                systemMid = NameSpaceHelper.transform(foundMid, fromNamespace.getToSystemTransformer());
1854            }
1855            
1856            if (MatcherHelper.matches(matcher, pattern.getModuleId(), systemMid)) {
1857                // The module corresponds to the searched module pattern
1858
foundModule = true;
1859                RevisionEntry[] rEntries = resolver.listRevisions(mEntry);
1860                Message.debug("found " + rEntries.length + " revisions for [" + mEntry.getOrganisation() + ", "+ mEntry.getModule() + "] on " + resolverName);
1861
1862                boolean foundRevision = false;
1863                for (int j = 0; j < rEntries.length; j++) {
1864                    RevisionEntry rEntry = rEntries[j];
1865                    
1866                    ModuleRevisionId foundMrid = ModuleRevisionId.newInstance(mEntry.getOrganisation(), mEntry.getModule(), rEntry.getRevision());
1867                    ModuleRevisionId systemMrid = foundMrid;
1868                    if (fromNamespace != null) {
1869                        systemMrid = fromNamespace.getToSystemTransformer().transform(foundMrid);
1870                    }
1871                    
1872                    if (MatcherHelper.matches(matcher, pattern, systemMrid)) {
1873                        // We have a matching module revision
1874
foundRevision = true;
1875                        mrids.add(systemMrid);
1876                    }
1877                }
1878                if (!foundRevision) {
1879                    Message.debug("no revision found matching "+pattern+" in [" + mEntry.getOrganisation() + "," + mEntry.getModule()+ "] using " + resolverName);
1880                }
1881            }
1882        }
1883        if (!foundModule) {
1884            Message.debug("no module found matching "+pattern+" using " + resolverName);
1885        }
1886        return mrids;
1887    }
1888
1889    /////////////////////////////////////////////////////////////////////////
1890
// RETRIEVE
1891
/////////////////////////////////////////////////////////////////////////
1892

1893    
1894    /**
1895     * example of destFilePattern :
1896     * - lib/[organisation]/[module]/[artifact]-[revision].[type]
1897     * - lib/[artifact].[type] : flatten with no revision
1898     * moduleId is used with confs and localCacheDirectory to determine
1899     * an ivy report file, used as input for the copy
1900     * If such a file does not exist for any conf (resolve has not been called before ?)
1901     * then an IllegalStateException is thrown and nothing is copied.
1902     */

1903    public int retrieve(ModuleId moduleId, String JavaDoc[] confs, final File JavaDoc cache, String JavaDoc destFilePattern) {
1904        return retrieve(moduleId, confs, cache, destFilePattern, null);
1905    }
1906    /**
1907     * If destIvyPattern is null no ivy files will be copied.
1908     */

1909    public int retrieve(ModuleId moduleId, String JavaDoc[] confs, final File JavaDoc cache, String JavaDoc destFilePattern, String JavaDoc destIvyPattern) {
1910        return retrieve(moduleId, confs, cache, destFilePattern, destIvyPattern, FilterHelper.NO_FILTER);
1911    }
1912    
1913    public int retrieve(ModuleId moduleId, String JavaDoc[] confs, final File JavaDoc cache, String JavaDoc destFilePattern, String JavaDoc destIvyPattern, Filter artifactFilter) {
1914        return retrieve(moduleId, confs, cache, destFilePattern, destIvyPattern, artifactFilter, false, false);
1915    }
1916    public int retrieve(ModuleId moduleId, String JavaDoc[] confs, final File JavaDoc cache, String JavaDoc destFilePattern, String JavaDoc destIvyPattern, Filter artifactFilter, boolean sync, boolean useOrigin) {
1917        if (artifactFilter == null) {
1918            artifactFilter = FilterHelper.NO_FILTER;
1919        }
1920        
1921        IvyContext.getContext().setIvy(this);
1922        IvyContext.getContext().setCache(cache);
1923        Message.info(":: retrieving :: "+moduleId+(sync?" [sync]":""));
1924        Message.info("\tconfs: "+Arrays.asList(confs));
1925        long start = System.currentTimeMillis();
1926        
1927        destFilePattern = IvyPatternHelper.substituteVariables(destFilePattern, getVariables());
1928        destIvyPattern = IvyPatternHelper.substituteVariables(destIvyPattern, getVariables());
1929        try {
1930            Map JavaDoc artifactsToCopy = determineArtifactsToCopy(moduleId, confs, cache, destFilePattern, destIvyPattern, artifactFilter);
1931            File JavaDoc fileRetrieveRoot = new File JavaDoc(IvyPatternHelper.getTokenRoot(destFilePattern));
1932            File JavaDoc ivyRetrieveRoot = destIvyPattern == null ? null : new File JavaDoc(IvyPatternHelper.getTokenRoot(destIvyPattern));
1933            Collection JavaDoc targetArtifactsStructure = new HashSet JavaDoc(); // Set(File) set of all paths which should be present at then end of retrieve (useful for sync)
1934
Collection JavaDoc targetIvysStructure = new HashSet JavaDoc(); // same for ivy files
1935

1936            // do retrieve
1937
int targetsCopied = 0;
1938            int targetsUpToDate = 0;
1939            for (Iterator JavaDoc iter = artifactsToCopy.keySet().iterator(); iter.hasNext();) {
1940                Artifact artifact = (Artifact)iter.next();
1941                File JavaDoc archive;
1942                if ("ivy".equals(artifact.getType())) {
1943                    archive = getIvyFileInCache(cache, artifact.getModuleRevisionId());
1944                } else {
1945                    archive = getArchiveFileInCache(cache, artifact, getSavedArtifactOrigin(cache, artifact), useOrigin);
1946                    if (!useOrigin && !archive.exists()) {
1947                        // file is not available in cache, maybe the last resolve was performed with useOrigin=true.
1948
// we try to use the best we can
1949
archive = getArchiveFileInCache(cache, artifact, getSavedArtifactOrigin(cache, artifact));
1950                    }
1951                }
1952                Set JavaDoc dest = (Set JavaDoc)artifactsToCopy.get(artifact);
1953                Message.verbose("\tretrieving "+archive);
1954                for (Iterator JavaDoc it2 = dest.iterator(); it2.hasNext();) {
1955                    checkInterrupted();
1956                    File JavaDoc destFile = new File JavaDoc((String JavaDoc)it2.next());
1957                    if (!_checkUpToDate || !upToDate(archive, destFile)) {
1958                        Message.verbose("\t\tto "+destFile);
1959                        FileUtil.copy(archive, destFile, null);
1960                        targetsCopied++;
1961                    } else {
1962                        Message.verbose("\t\tto "+destFile+" [NOT REQUIRED]");
1963                        targetsUpToDate++;
1964                    }
1965                    if ("ivy".equals(artifact.getType())) {
1966                        targetIvysStructure.addAll(FileUtil.getPathFiles(ivyRetrieveRoot, destFile));
1967                    } else {
1968                        targetArtifactsStructure.addAll(FileUtil.getPathFiles(fileRetrieveRoot, destFile));
1969                    }
1970                }
1971            }
1972            
1973            if (sync) {
1974                Message.verbose("\tsyncing...");
1975                Collection JavaDoc existingArtifacts = FileUtil.listAll(fileRetrieveRoot);
1976                Collection JavaDoc existingIvys = ivyRetrieveRoot == null ? null : FileUtil.listAll(ivyRetrieveRoot);
1977
1978                if (fileRetrieveRoot.equals(ivyRetrieveRoot)) {
1979                    Collection JavaDoc target = targetArtifactsStructure;
1980                    target.addAll(targetIvysStructure);
1981                    Collection JavaDoc existing = existingArtifacts;
1982                    existing.addAll(existingIvys);
1983                    sync(target, existing);
1984                } else {
1985                    sync(targetArtifactsStructure, existingArtifacts);
1986                    if (existingIvys != null) {
1987                        sync(targetIvysStructure, existingIvys);
1988                    }
1989                }
1990            }
1991            Message.info("\t"+targetsCopied+" artifacts copied, "+targetsUpToDate+" already retrieved");
1992            Message.verbose("\tretrieve done ("+(System.currentTimeMillis()-start)+"ms)");
1993            
1994            return targetsCopied;
1995        } catch (Exception JavaDoc ex) {
1996            throw new RuntimeException JavaDoc("problem during retrieve of "+moduleId+": "+ex, ex);
1997        }
1998    }
1999
2000    private void sync(Collection JavaDoc target, Collection JavaDoc existing) {
2001        Collection JavaDoc toRemove = new HashSet JavaDoc();
2002        for (Iterator JavaDoc iter = existing.iterator(); iter.hasNext();) {
2003            File JavaDoc file = (File JavaDoc) iter.next();
2004            toRemove.add(file.getAbsoluteFile());
2005        }
2006        for (Iterator JavaDoc iter = target.iterator(); iter.hasNext();) {
2007            File JavaDoc file = (File JavaDoc) iter.next();
2008            toRemove.remove(file.getAbsoluteFile());
2009        }
2010        for (Iterator JavaDoc iter = toRemove.iterator(); iter.hasNext();) {
2011            File JavaDoc file = (File JavaDoc) iter.next();
2012            if (file.exists()) {
2013                Message.verbose("\t\tdeleting "+file);
2014                FileUtil.forceDelete(file);
2015            }
2016        }
2017    }
2018
2019    public Map JavaDoc determineArtifactsToCopy(ModuleId moduleId, String JavaDoc[] confs, final File JavaDoc cache, String JavaDoc destFilePattern, String JavaDoc destIvyPattern) throws ParseException JavaDoc, IOException JavaDoc {
2020        return determineArtifactsToCopy(moduleId, confs, cache, destFilePattern, destIvyPattern, FilterHelper.NO_FILTER);
2021    }
2022    
2023    public Map JavaDoc determineArtifactsToCopy(ModuleId moduleId, String JavaDoc[] confs, final File JavaDoc cache, String JavaDoc destFilePattern, String JavaDoc destIvyPattern, Filter artifactFilter) throws ParseException JavaDoc, IOException JavaDoc {
2024        IvyContext.getContext().setIvy(this);
2025        IvyContext.getContext().setCache(cache);
2026        
2027        if (artifactFilter == null) {
2028            artifactFilter = FilterHelper.NO_FILTER;
2029        }
2030        
2031        // find what we must retrieve where
2032
final Map JavaDoc artifactsToCopy = new HashMap JavaDoc(); // Artifact source -> Set (String copyDestAbsolutePath)
2033
final Map JavaDoc conflictsMap = new HashMap JavaDoc(); // String copyDestAbsolutePath -> Set (Artifact source)
2034
final Map JavaDoc conflictsConfMap = new HashMap JavaDoc(); // String copyDestAbsolutePath -> Set (String conf)
2035
XmlReportParser parser = new XmlReportParser();
2036        for (int i = 0; i < confs.length; i++) {
2037            final String JavaDoc conf = confs[i];
2038            Collection JavaDoc artifacts = new ArrayList JavaDoc(Arrays.asList(parser.getArtifacts(moduleId, conf, cache)));
2039            if (destIvyPattern != null) {
2040                ModuleRevisionId[] mrids = parser.getRealDependencyRevisionIds(moduleId, conf, cache);
2041                for (int j = 0; j < mrids.length; j++) {
2042                    artifacts.add(DefaultArtifact.newIvyArtifact(mrids[j], null));
2043                }
2044            }
2045            for (Iterator JavaDoc iter = artifacts.iterator(); iter.hasNext();) {
2046                Artifact artifact = (Artifact)iter.next();
2047                String JavaDoc destPattern = "ivy".equals(artifact.getType()) ? destIvyPattern: destFilePattern;
2048                
2049                if (!"ivy".equals(artifact.getType()) && !artifactFilter.accept(artifact)) {
2050                    continue; // skip this artifact, the filter didn't accept it!
2051
}
2052                
2053                String JavaDoc destFileName = IvyPatternHelper.substitute(destPattern, artifact, conf);
2054                
2055                Set JavaDoc dest = (Set JavaDoc)artifactsToCopy.get(artifact);
2056                if (dest == null) {
2057                    dest = new HashSet JavaDoc();
2058                    artifactsToCopy.put(artifact, dest);
2059                }
2060                String JavaDoc copyDest = new File JavaDoc(destFileName).getAbsolutePath();
2061                dest.add(copyDest);
2062                
2063                Set JavaDoc conflicts = (Set JavaDoc)conflictsMap.get(copyDest);
2064                Set JavaDoc conflictsConf = (Set JavaDoc)conflictsConfMap.get(copyDest);
2065                if (conflicts == null) {
2066                    conflicts = new HashSet JavaDoc();
2067                    conflictsMap.put(copyDest, conflicts);
2068                }
2069                if (conflictsConf == null) {
2070                    conflictsConf = new HashSet JavaDoc();
2071                    conflictsConfMap.put(copyDest, conflictsConf);
2072                }
2073                conflicts.add(artifact);
2074                conflictsConf.add(conf);
2075            }
2076        }
2077        
2078        // resolve conflicts if any
2079
for (Iterator JavaDoc iter = conflictsMap.keySet().iterator(); iter.hasNext();) {
2080            String JavaDoc copyDest = (String JavaDoc)iter.next();
2081            Set JavaDoc artifacts = (Set JavaDoc)conflictsMap.get(copyDest);
2082            Set JavaDoc conflictsConfs = (Set JavaDoc)conflictsConfMap.get(copyDest);
2083            if (artifacts.size() > 1) {
2084                List JavaDoc artifactsList = new ArrayList JavaDoc(artifacts);
2085                // conflicts battle is resolved by a sort using a conflict resolving policy comparator
2086
// which consider as greater a winning artifact
2087
Collections.sort(artifactsList, getConflictResolvingPolicy());
2088                // after the sort, the winning artifact is the greatest one, i.e. the last one
2089
Message.info("\tconflict on "+copyDest+" in "+conflictsConfs+": "+((Artifact)artifactsList.get(artifactsList.size() -1)).getModuleRevisionId().getRevision()+" won");
2090                
2091                // we now iterate over the list beginning with the artifact preceding the winner,
2092
// and going backward to the least artifact
2093
for (int i=artifactsList.size() - 2; i >=0; i--) {
2094                    Artifact looser = (Artifact)artifactsList.get(i);
2095                    Message.verbose("\t\tremoving conflict looser artifact: "+looser);
2096                    // for each loser, we remove the pair (loser - copyDest) in the artifactsToCopy map
2097
Set JavaDoc dest = (Set JavaDoc)artifactsToCopy.get(looser);
2098                    dest.remove(copyDest);
2099                    if (dest.isEmpty()) {
2100                        artifactsToCopy.remove(looser);
2101                    }
2102                }
2103            }
2104        }
2105        return artifactsToCopy;
2106    }
2107    
2108    private boolean upToDate(File JavaDoc source, File JavaDoc target) {
2109        if (!target.exists()) {
2110            return false;
2111        }
2112        return source.lastModified() <= target.lastModified();
2113    }
2114
2115    /**
2116     * The returned comparator should consider greater the artifact which
2117     * gains the conflict battle.
2118     * This is used only during retrieve... prefer resolve conflict manager
2119     * to resolve conflicts.
2120     * @return
2121     */

2122    private Comparator JavaDoc getConflictResolvingPolicy() {
2123        return new Comparator JavaDoc() {
2124            // younger conflict resolving policy
2125
public int compare(Object JavaDoc o1, Object JavaDoc o2) {
2126                Artifact a1 = (Artifact)o1;
2127                Artifact a2 = (Artifact)o2;
2128                if (a1.getPublicationDate().after(a2.getPublicationDate())) {
2129                    // a1 is after a2 <=> a1 is younger than a2 <=> a1 wins the conflict battle
2130
return +1;
2131                } else if (a1.getPublicationDate().before(a2.getPublicationDate())) {
2132                    // a1 is before a2 <=> a2 is younger than a1 <=> a2 wins the conflict battle
2133
return -1;
2134                } else {
2135                    return 0;
2136                }
2137            }
2138        };
2139    }
2140
2141    /////////////////////////////////////////////////////////////////////////
2142
// PUBLISH
2143
/////////////////////////////////////////////////////////////////////////
2144
public void deliver(ModuleRevisionId mrid,
2145            String JavaDoc revision,
2146            File JavaDoc cache,
2147            String JavaDoc destIvyPattern,
2148            String JavaDoc status,
2149            Date JavaDoc pubdate,
2150            PublishingDependencyRevisionResolver pdrResolver,
2151            boolean validate
2152            ) throws IOException JavaDoc, ParseException JavaDoc {
2153        deliver(mrid, revision, cache, destIvyPattern, status, pubdate, pdrResolver, validate, true);
2154    }
2155    
2156    /**
2157     * delivers a resolved ivy file based upon last resolve call status and
2158     * the given PublishingDependencyRevisionResolver.
2159     * If resolve report file cannot be found in cache, then it throws
2160     * an IllegalStateException (maybe resolve has not been called before ?)
2161     * Moreover, the given PublishingDependencyRevisionResolver is used for each
2162     * dependency to get its published information. This can particularly useful
2163     * when the publish is made for a delivery, and when we wish to deliver each
2164     * dependency which is still in integration. The PublishingDependencyRevisionResolver
2165     * can then do the delivering work for the dependency and return the new (delivered)
2166     * dependency info (with the delivered revision). Note that
2167     * PublishingDependencyRevisionResolver is only called for each <b>direct</b> dependency.
2168     *
2169     * @param status the new status, null to keep the old one
2170     * @throws ParseException
2171     */

2172    public void deliver(ModuleRevisionId mrid,
2173            String JavaDoc revision,
2174            File JavaDoc cache,
2175            String JavaDoc destIvyPattern,
2176            String JavaDoc status,
2177            Date JavaDoc pubdate,
2178            PublishingDependencyRevisionResolver pdrResolver,
2179            boolean validate,
2180            boolean resolveDynamicRevisions) throws IOException JavaDoc, ParseException JavaDoc {
2181        IvyContext.getContext().setIvy(this);
2182        IvyContext.getContext().setCache(cache);
2183        Message.info(":: delivering :: "+mrid+" :: "+revision+" :: "+status+" :: "+pubdate);
2184        Message.verbose("\tvalidate = "+validate);
2185        long start = System.currentTimeMillis();
2186        destIvyPattern = substitute(destIvyPattern);
2187        
2188        // 1) find the resolved module descriptor in cache
2189
File JavaDoc ivyFile = getResolvedIvyFileInCache(cache, mrid);
2190        if (!ivyFile.exists()) {
2191            throw new IllegalStateException JavaDoc("ivy file not found in cache for "+mrid+": please resolve dependencies before publishing ("+ivyFile+")");
2192        }
2193        ModuleDescriptor md = null;
2194        URL JavaDoc ivyFileURL = null;
2195        try {
2196            ivyFileURL = ivyFile.toURL();
2197            md = XmlModuleDescriptorParser.getInstance().parseDescriptor(this, ivyFileURL, validate);
2198            md.setResolvedModuleRevisionId(ModuleRevisionId.newInstance(mrid, revision));
2199            md.setResolvedPublicationDate(pubdate);
2200        } catch (MalformedURLException JavaDoc e) {
2201            throw new RuntimeException JavaDoc("malformed url obtained for file "+ivyFile);
2202        } catch (ParseException JavaDoc e) {
2203            throw new IllegalStateException JavaDoc("bad ivy file in cache for "+mrid+": please clean and resolve again");
2204        }
2205        
2206        // 2) parse resolvedRevisions From properties file
2207
Map JavaDoc resolvedRevisions = new HashMap JavaDoc(); // Map (ModuleId -> String revision)
2208
Map JavaDoc dependenciesStatus = new HashMap JavaDoc(); // Map (ModuleId -> String status)
2209
File JavaDoc ivyProperties = getResolvedIvyPropertiesInCache(cache, mrid);
2210        if (!ivyProperties.exists()) {
2211            throw new IllegalStateException JavaDoc("ivy properties not found in cache for "+mrid+": please resolve dependencies before publishing ("+ivyFile+")");
2212        }
2213        Properties JavaDoc props = new Properties JavaDoc();
2214        props.load(new FileInputStream JavaDoc(ivyProperties));
2215        
2216        for (Iterator JavaDoc iter = props.keySet().iterator(); iter.hasNext();) {
2217            String JavaDoc depMridStr = (String JavaDoc)iter.next();
2218            String JavaDoc[] parts = props.getProperty(depMridStr).split(" ");
2219            ModuleRevisionId decodedMrid = ModuleRevisionId.decode(depMridStr);
2220            if (resolveDynamicRevisions) {
2221                resolvedRevisions.put(decodedMrid, parts[0]);
2222            }
2223            dependenciesStatus.put(decodedMrid, parts[1]);
2224        }
2225        
2226        // 3) use pdrResolver to resolve dependencies info
2227
Map JavaDoc resolvedDependencies = new HashMap JavaDoc(); // Map (ModuleRevisionId -> String revision)
2228
DependencyDescriptor[] dependencies = md.getDependencies();
2229        for (int i = 0; i < dependencies.length; i++) {
2230            String JavaDoc rev = (String JavaDoc)resolvedRevisions.get(dependencies[i].getDependencyRevisionId());
2231            if (rev == null) {
2232                rev = dependencies[i].getDependencyRevisionId().getRevision();
2233            }
2234            String JavaDoc depStatus = (String JavaDoc)dependenciesStatus.get(dependencies[i].getDependencyRevisionId());
2235            resolvedDependencies.put(dependencies[i].getDependencyRevisionId(),
2236                    pdrResolver.resolve(md, status,
2237                            ModuleRevisionId.newInstance(dependencies[i].getDependencyRevisionId(), rev),
2238                            depStatus));
2239        }
2240        
2241        // 4) copy the source resolved ivy to the destination specified,
2242
// updating status, revision and dependency revisions obtained by
2243
// PublishingDependencyRevisionResolver
2244
String JavaDoc publishedIvy = IvyPatternHelper.substitute(destIvyPattern, md.getResolvedModuleRevisionId());
2245        Message.info("\tdelivering ivy file to "+publishedIvy);
2246        try {
2247            XmlModuleDescriptorUpdater.update(this, ivyFileURL,
2248                    new File JavaDoc(publishedIvy),
2249                    resolvedDependencies, status, revision, pubdate, null, true);
2250        } catch (SAXException JavaDoc ex) {
2251            throw new IllegalStateException JavaDoc("bad ivy file in cache for "+mrid+": please clean and resolve again");
2252        }
2253        
2254        Message.verbose("\tdeliver done ("+(System.currentTimeMillis()-start)+"ms)");
2255    }
2256
2257    /**
2258     *
2259     * @param pubrevision
2260     * @param resolverName the name of a resolver to use for publication
2261     * @param srcArtifactPattern a pattern to find artifacts to publish with the given resolver
2262     * @param srcIvyPattern a pattern to find ivy file to publish, null if ivy file should not be published
2263     * @return a collection of missing artifacts (those that are not published)
2264     * @throws ParseException
2265     */

2266    public Collection JavaDoc publish(ModuleRevisionId mrid, String JavaDoc pubrevision, File JavaDoc cache, String JavaDoc srcArtifactPattern, String JavaDoc resolverName, String JavaDoc srcIvyPattern, boolean validate) throws IOException JavaDoc {
2267        return publish(mrid, pubrevision, cache, srcArtifactPattern, resolverName, srcIvyPattern, validate, false);
2268    }
2269    /**
2270     *
2271     * @param pubrevision
2272     * @param resolverName the name of a resolver to use for publication
2273     * @param srcArtifactPattern a pattern to find artifacts to publish with the given resolver
2274     * @param srcIvyPattern a pattern to find ivy file to publish, null if ivy file should not be published
2275     * @return a collection of missing artifacts (those that are not published)
2276     * @throws ParseException
2277     */

2278    public Collection JavaDoc publish(ModuleRevisionId mrid, String JavaDoc pubrevision, File JavaDoc cache, String JavaDoc srcArtifactPattern, String JavaDoc resolverName, String JavaDoc srcIvyPattern, boolean validate, boolean overwrite) throws IOException JavaDoc {
2279        return publish(mrid, pubrevision, cache, srcArtifactPattern, resolverName, srcIvyPattern, null, null, null, validate, overwrite, false, null);
2280    }
2281    public Collection JavaDoc publish(ModuleRevisionId mrid, String JavaDoc pubrevision, File JavaDoc cache, String JavaDoc srcArtifactPattern, String JavaDoc resolverName, String JavaDoc srcIvyPattern, String JavaDoc status, Date JavaDoc pubdate, Artifact[] extraArtifacts, boolean validate, boolean overwrite, boolean update, String JavaDoc conf) throws IOException JavaDoc {
2282        return publish(mrid, pubrevision, cache, Collections.singleton(srcArtifactPattern), resolverName, srcIvyPattern, status, pubdate, extraArtifacts, validate, overwrite, update, conf);
2283    }
2284    /**
2285     * Publishes a module to the repository.
2286     *
2287     * The publish can update the ivy file to publish if update is set to true. In this case it will use
2288     * the given pubrevision, pubdate and status. If pudate is null it will default to the current date.
2289     * If status is null it will default to the current ivy file status (which itself defaults to integration if none is found).
2290     * If update is false, then if the revision is not the same in the ivy file than the one expected (given as parameter),
2291     * this method will fail with an IllegalArgumentException.
2292     * pubdate and status are not used if update is false.
2293     * extra artifacts can be used to publish more artifacts than actually declared in the ivy file.
2294     * This can be useful to publish additional metadata or reports.
2295     * The extra artifacts array can be null (= no extra artifacts), and if non null only the name, type, ext url
2296     * and extra attributes of the artifacts are really used. Other methods can return null safely.
2297     *
2298     * @param mrid
2299     * @param pubrevision
2300     * @param cache
2301     * @param srcArtifactPattern
2302     * @param resolverName
2303     * @param srcIvyPattern
2304     * @param status
2305     * @param pubdate
2306     * @param validate
2307     * @param overwrite
2308     * @param update
2309     * @return
2310     * @throws IOException
2311     */

2312    public Collection JavaDoc publish(ModuleRevisionId mrid, String JavaDoc pubrevision, File JavaDoc cache, Collection JavaDoc srcArtifactPattern, String JavaDoc resolverName, String JavaDoc srcIvyPattern, String JavaDoc status, Date JavaDoc pubdate, Artifact[] extraArtifacts, boolean validate, boolean overwrite, boolean update, String JavaDoc conf) throws IOException JavaDoc {
2313        IvyContext.getContext().setIvy(this);
2314        IvyContext.getContext().setCache(cache);
2315        Message.info(":: publishing :: "+mrid.getModuleId());
2316        Message.verbose("\tvalidate = "+validate);
2317        long start = System.currentTimeMillis();
2318        srcIvyPattern = substitute(srcIvyPattern);
2319        // 1) find the resolved module descriptor
2320
ModuleRevisionId pubmrid = ModuleRevisionId.newInstance(mrid, pubrevision);
2321        File JavaDoc ivyFile;
2322        if (srcIvyPattern != null) {
2323            ivyFile = new File JavaDoc(IvyPatternHelper.substitute(srcIvyPattern, DefaultArtifact.newIvyArtifact(pubmrid, new Date JavaDoc())));
2324            if (!ivyFile.exists()) {
2325                throw new IllegalArgumentException JavaDoc("ivy file to publish not found for "+mrid+": call deliver before ("+ivyFile+")");
2326            }
2327        } else {
2328            ivyFile = getResolvedIvyFileInCache(cache, mrid);
2329            if (!ivyFile.exists()) {
2330                throw new IllegalStateException JavaDoc("ivy file not found in cache for "+mrid+": please resolve dependencies before publishing ("+ivyFile+")");
2331            }
2332        }
2333        
2334        ModuleDescriptor md = null;
2335        URL JavaDoc ivyFileURL = null;
2336        try {
2337            ivyFileURL = ivyFile.toURL();
2338            md = XmlModuleDescriptorParser.getInstance().parseDescriptor(this, ivyFileURL, false);
2339            if (srcIvyPattern != null) {
2340                if (!pubrevision.equals(md.getModuleRevisionId().getRevision())) {
2341                    if (update) {
2342                        File JavaDoc tmp = File.createTempFile("ivy", ".xml");
2343                        tmp.deleteOnExit();
2344                        try {
2345                            XmlModuleDescriptorUpdater.update(this, ivyFileURL, tmp, new HashMap JavaDoc(), status==null?md.getStatus():status, pubrevision, pubdate==null?new Date JavaDoc():pubdate, null, true);
2346                            ivyFile = tmp;
2347                            // we parse the new file to get updated module descriptor
2348
md = XmlModuleDescriptorParser.getInstance().parseDescriptor(this, ivyFile.toURL(), false);
2349                            srcIvyPattern = ivyFile.getAbsolutePath();
2350                        } catch (SAXException JavaDoc e) {
2351                            throw new IllegalStateException JavaDoc("bad ivy file for "+mrid+": "+ivyFile+": "+e);
2352                        }
2353                    } else {
2354                        throw new IllegalArgumentException JavaDoc("cannot publish "+ivyFile+" as "+pubrevision+": bad revision found in ivy file. Use deliver before.");
2355                    }
2356                }
2357            } else {
2358                md.setResolvedModuleRevisionId(pubmrid);
2359            }
2360        } catch (MalformedURLException JavaDoc e) {
2361            throw new RuntimeException JavaDoc("malformed url obtained for file "+ivyFile);
2362        } catch (ParseException JavaDoc e) {
2363            throw new IllegalStateException JavaDoc("bad ivy file for "+mrid+": "+ivyFile+": "+e);
2364        }
2365        
2366        DependencyResolver resolver = getResolver(resolverName);
2367        if (resolver == null) {
2368            throw new IllegalArgumentException JavaDoc("unknown resolver "+resolverName);
2369        }
2370        
2371        // collect all declared artifacts of this module
2372
Collection JavaDoc missing = publish(md, resolver, srcArtifactPattern, srcIvyPattern, extraArtifacts, overwrite, conf);
2373        Message.verbose("\tpublish done ("+(System.currentTimeMillis()-start)+"ms)");
2374        return missing;
2375    }
2376
2377    private Collection JavaDoc publish(ModuleDescriptor md, DependencyResolver resolver, Collection JavaDoc srcArtifactPattern, String JavaDoc srcIvyPattern, Artifact[] extraArtifacts, boolean overwrite, String JavaDoc conf) throws IOException JavaDoc {
2378        Collection JavaDoc missing = new ArrayList JavaDoc();
2379        Set JavaDoc artifactsSet = new HashSet JavaDoc();
2380        String JavaDoc[] confs;
2381        if (null == conf || "".equals(conf)) {
2382            confs = md.getConfigurationsNames();
2383        } else {
2384            StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(conf, ",");
2385            confs = new String JavaDoc[st.countTokens()];
2386            int counter = 0;
2387            while (st.hasMoreTokens()) {
2388                confs[counter] = st.nextToken().trim();
2389                counter++;
2390            }
2391        }
2392
2393        for (int i = 0; i < confs.length; i++) {
2394            Artifact[] artifacts = md.getArtifacts(confs[i]);
2395            for (int j = 0; j < artifacts.length; j++) {
2396                artifactsSet.add(artifacts[j]);
2397            }
2398        }
2399        if (extraArtifacts != null) {
2400            for (int i = 0; i < extraArtifacts.length; i++) {
2401                artifactsSet.add(new MDArtifact(md, extraArtifacts[i].getName(), extraArtifacts[i].getType(), extraArtifacts[i].getExt(), extraArtifacts[i].getUrl(), extraArtifacts[i].getExtraAttributes()));
2402            }
2403        }
2404        // for each declared published artifact in this descriptor, do:
2405
for (Iterator JavaDoc iter = artifactsSet.iterator(); iter.hasNext();) {
2406            Artifact artifact = (Artifact) iter.next();
2407            // 1) copy the artifact using src patterns and resolver
2408
boolean published = false;
2409            for (Iterator JavaDoc iterator = srcArtifactPattern.iterator(); iterator.hasNext() && !published;) {
2410                String JavaDoc pattern = (String JavaDoc) iterator.next();
2411                published = publish(artifact, substitute(pattern), resolver, overwrite);
2412            }
2413            if (!published) {
2414                Message.info("missing artifact "+artifact+":");
2415                for (Iterator JavaDoc iterator = srcArtifactPattern.iterator(); iterator.hasNext();) {
2416                    String JavaDoc pattern = (String JavaDoc) iterator.next();
2417                    Message.info("\t"+new File JavaDoc(IvyPatternHelper.substitute(pattern, artifact))+" file does not exist");
2418                }
2419                missing.add(artifact);
2420            }
2421        }
2422        if (srcIvyPattern != null) {
2423            Artifact artifact = MDArtifact.newIvyArtifact(md);
2424            if (!publish(artifact, srcIvyPattern, resolver, overwrite)) {
2425                Message.info("missing ivy file for "+md.getModuleRevisionId()+": "+new File JavaDoc(IvyPatternHelper.substitute(srcIvyPattern, artifact))+" file does not exist");
2426                missing.add(artifact);
2427            }
2428        }
2429        return missing;
2430    }
2431
2432    private boolean publish(Artifact artifact, String JavaDoc srcArtifactPattern, DependencyResolver resolver, boolean overwrite) throws IOException JavaDoc {
2433        checkInterrupted();
2434        File JavaDoc src = new File JavaDoc(IvyPatternHelper.substitute(srcArtifactPattern, artifact));
2435        if (src.exists()) {
2436            resolver.publish(artifact, src, overwrite);
2437            return true;
2438        } else {
2439            return false;
2440        }
2441    }
2442
2443    /////////////////////////////////////////////////////////////////////////
2444
// SORT
2445
/////////////////////////////////////////////////////////////////////////
2446

2447    /**
2448     * Sorts the collection of IvyNode from the less dependent to the more dependent
2449     */

2450    public List JavaDoc sortNodes(Collection JavaDoc nodes) {
2451        IvyContext.getContext().setIvy(this);
2452        return ModuleDescriptorSorter.sortNodes(getVersionMatcher(), nodes);
2453    }
2454
2455
2456    /**
2457     * Sorts the given ModuleDescriptors from the less dependent to the more dependent.
2458     * This sort ensures that a ModuleDescriptor is always found in the list before all
2459     * ModuleDescriptors depending directly on it.
2460     * @param moduleDescriptors a Collection of ModuleDescriptor to sort
2461     * @return a List of sorted ModuleDescriptors
2462     */

2463    public List JavaDoc sortModuleDescriptors(Collection JavaDoc moduleDescriptors) {
2464        IvyContext.getContext().setIvy(this);
2465        return ModuleDescriptorSorter.sortModuleDescriptors(getVersionMatcher(), moduleDescriptors);
2466    }
2467    
2468    /////////////////////////////////////////////////////////////////////////
2469
// CACHE
2470
/////////////////////////////////////////////////////////////////////////
2471

2472    public File JavaDoc getResolvedIvyFileInCache(File JavaDoc cache, ModuleRevisionId mrid) {
2473        IvyContext.getContext().setIvy(this);
2474        IvyContext.getContext().setCache(cache);
2475        return new File JavaDoc(cache, IvyPatternHelper.substitute(_cacheResolvedIvyPattern, mrid.getOrganisation(), mrid.getName(), mrid.getRevision(), "ivy", "ivy", "xml"));
2476    }
2477
2478    public File JavaDoc getResolvedIvyPropertiesInCache(File JavaDoc cache, ModuleRevisionId mrid) {
2479        IvyContext.getContext().setIvy(this);
2480        IvyContext.getContext().setCache(cache);
2481        return new File JavaDoc(cache, IvyPatternHelper.substitute(_cacheResolvedIvyPropertiesPattern, mrid.getOrganisation(), mrid.getName(), mrid.getRevision(), "ivy", "ivy", "xml"));
2482    }
2483
2484    public File JavaDoc getIvyFileInCache(File JavaDoc cache, ModuleRevisionId mrid) {
2485        IvyContext.getContext().setIvy(this);
2486        IvyContext.getContext().setCache(cache);
2487        return new File JavaDoc(cache, IvyPatternHelper.substitute(_cacheIvyPattern, DefaultArtifact.newIvyArtifact(mrid, null)));
2488    }
2489
2490    /**
2491     * Returns a File object pointing to where the artifact can be found on the local file system.
2492     * This is usually in the cache, but it can be directly in the repository if it is local
2493     * and if the resolve has been done with useOrigin = true
2494     *
2495     */

2496    public File JavaDoc getArchiveFileInCache(File JavaDoc cache, Artifact artifact) {
2497        IvyContext.getContext().setIvy(this);
2498        IvyContext.getContext().setCache(cache);
2499        ArtifactOrigin origin = getSavedArtifactOrigin(cache, artifact);
2500        return getArchiveFileInCache(cache, artifact, origin);
2501    }
2502    
2503    /**
2504     * Returns a File object pointing to where the artifact can be found on the local file system.
2505     * This is usually in the cache, but it can be directly in the repository if it is local
2506     * and if the resolve has been done with useOrigin = true
2507     *
2508     */

2509    public File JavaDoc getArchiveFileInCache(File JavaDoc cache, Artifact artifact, ArtifactOrigin origin) {
2510        IvyContext.getContext().setIvy(this);
2511        IvyContext.getContext().setCache(cache);
2512        File JavaDoc archive = new File JavaDoc(cache, getArchivePathInCache(artifact, origin));
2513        if (!archive.exists() && origin != null && origin.isLocal()) {
2514            File JavaDoc original = new File JavaDoc(origin.getLocation());
2515            if (original.exists()) {
2516                return original;
2517            }
2518        }
2519        return archive;
2520    }
2521    /**
2522     * Returns a File object pointing to where the artifact can be found on the local file system,
2523     * using or not the original location depending on the availability of origin information provided
2524     * as parameter and the setting of useOrigin.
2525     *
2526     * If useOrigin is false, this method will always return the file in the cache.
2527     *
2528     */

2529    public File JavaDoc getArchiveFileInCache(File JavaDoc cache, Artifact artifact, ArtifactOrigin origin, boolean useOrigin) {
2530        IvyContext.getContext().setIvy(this);
2531        IvyContext.getContext().setCache(cache);
2532        if (useOrigin && origin != null && origin.isLocal()) {
2533            return new File JavaDoc(origin.getLocation());
2534        } else {
2535            return new File JavaDoc(cache, getArchivePathInCache(artifact, origin));
2536        }
2537    }
2538    
2539    /**
2540     * deprecated: use getArchiveFileInCache(File cache, Artifact artifact) instead
2541     */

2542    public File JavaDoc getArchiveFileInCache(File JavaDoc cache, String JavaDoc organisation, String JavaDoc module, String JavaDoc revision, String JavaDoc artifact, String JavaDoc type, String JavaDoc ext) {
2543        IvyContext.getContext().setIvy(this);
2544        IvyContext.getContext().setCache(cache);
2545        return new File JavaDoc(cache, getArchivePathInCache(organisation, module, revision, artifact, type, ext));
2546    }
2547    
2548    /**
2549     * @deprecated use getArchivePathInCache(Artifact artifact, ArtifactOrigin origin) instead.
2550     * @param artifact
2551     * @return
2552     */

2553    public String JavaDoc getArchivePathInCache(Artifact artifact) {
2554        IvyContext.getContext().setIvy(this);
2555        return IvyPatternHelper.substitute(_cacheArtifactPattern, artifact);
2556    }
2557    
2558    public String JavaDoc getArchivePathInCache(Artifact artifact, ArtifactOrigin origin) {
2559        IvyContext.getContext().setIvy(this);
2560        return IvyPatternHelper.substitute(_cacheArtifactPattern, artifact, origin);
2561    }
2562    
2563    /**
2564     * @deprecated
2565     */

2566    public String JavaDoc getArchivePathInCache(String JavaDoc organisation, String JavaDoc module, String JavaDoc revision, String JavaDoc artifact, String JavaDoc type, String JavaDoc ext) {
2567        IvyContext.getContext().setIvy(this);
2568        return getArchivePathInCache(new DefaultArtifact(ModuleRevisionId.newInstance(organisation, module, revision), new Date JavaDoc(), artifact, type, ext));
2569    }
2570    
2571// public File getOriginFileInCache(File cache, Artifact artifact) {
2572
// return new File(cache, getOriginPathInCache(artifact));
2573
// }
2574
//
2575
// public String getOriginPathInCache(Artifact artifact) {
2576
// return getArchivePathInCache(artifact) + ".origin";
2577
// }
2578

2579    /**
2580     * Interrupts the current running operation, no later than
2581     * interruptTimeout milliseconds after the call
2582     */

2583    public void interrupt() {
2584        Thread JavaDoc operatingThread = IvyContext.getContext().getOperatingThread();
2585        interrupt(operatingThread);
2586    }
2587
2588    /**
2589     * Interrupts the current running operation in the given operating thread,
2590     * no later than interruptTimeout milliseconds after the call
2591     */

2592    public void interrupt(Thread JavaDoc operatingThread) {
2593        if (operatingThread != null && operatingThread.isAlive()) {
2594            if (operatingThread == Thread.currentThread()) {
2595                throw new IllegalStateException JavaDoc("cannot call interrupt from ivy operating thread");
2596            }
2597            Message.verbose("interrupting operating thread...");
2598            operatingThread.interrupt();
2599            synchronized (this) {
2600                _interrupted = true;
2601            }
2602            try {
2603                Message.verbose("waiting clean interruption of operating thread");
2604                operatingThread.join(_interruptTimeout);
2605            } catch (InterruptedException JavaDoc e) {
2606            }
2607            if (operatingThread.isAlive()) {
2608                Message.warn("waited clean interruption for too long: stopping operating thread");
2609                operatingThread.stop();
2610            }
2611            synchronized (this) {
2612                _interrupted = false;
2613            }
2614        }
2615    }
2616    
2617    public static String JavaDoc getLocalHostName() {
2618        try {
2619            return InetAddress.getLocalHost().getHostName();
2620        } catch (UnknownHostException JavaDoc e) {
2621            return "localhost";
2622        }
2623    }
2624    
2625
2626    /**
2627     * Returns an empty array when no token values are found.
2628     *
2629     * @param token
2630     * @param otherTokenValues
2631     * @return
2632     */

2633    public String JavaDoc[] listTokenValues(String JavaDoc token, Map JavaDoc otherTokenValues) {
2634        List JavaDoc r = new ArrayList JavaDoc();
2635        for (Iterator JavaDoc iter = _resolversMap.values().iterator(); iter.hasNext();) {
2636            DependencyResolver resolver = (DependencyResolver)iter.next();
2637            r.addAll(Arrays.asList(resolver.listTokenValues(token, otherTokenValues)));
2638        }
2639        return (String JavaDoc[])r.toArray(new String JavaDoc[r.size()]);
2640    }
2641    
2642    public OrganisationEntry[] listOrganisationEntries() {
2643        List JavaDoc entries = new ArrayList JavaDoc();
2644        for (Iterator JavaDoc iter = _resolversMap.values().iterator(); iter.hasNext();) {
2645            DependencyResolver resolver = (DependencyResolver)iter.next();
2646            entries.addAll(Arrays.asList(resolver.listOrganisations()));
2647        }
2648        return (OrganisationEntry[])entries.toArray(new OrganisationEntry[entries.size()]);
2649    }
2650    public String JavaDoc[] listOrganisations() {
2651        Collection JavaDoc orgs = new HashSet JavaDoc();
2652        for (Iterator JavaDoc iter = _resolversMap.values().iterator(); iter.hasNext();) {
2653            DependencyResolver resolver = (DependencyResolver)iter.next();
2654            OrganisationEntry[] entries = resolver.listOrganisations();
2655            if (entries != null) {
2656                for (int i = 0; i < entries.length; i++) {
2657                    if (entries[i] != null) {
2658                        orgs.add(entries[i].getOrganisation());
2659                    }
2660                }
2661            }
2662        }
2663        return (String JavaDoc[])orgs.toArray(new String JavaDoc[orgs.size()]);
2664    }
2665    public ModuleEntry[] listModuleEntries(OrganisationEntry org) {
2666        List JavaDoc entries = new ArrayList JavaDoc();
2667        for (Iterator JavaDoc iter = _resolversMap.values().iterator(); iter.hasNext();) {
2668            DependencyResolver resolver = (DependencyResolver)iter.next();
2669            entries.addAll(Arrays.asList(resolver.listModules(org)));
2670        }
2671        return (ModuleEntry[])entries.toArray(new ModuleEntry[entries.size()]);
2672    }
2673    public String JavaDoc[] listModules(String JavaDoc org) {
2674        List JavaDoc mods = new ArrayList JavaDoc();
2675        for (Iterator JavaDoc iter = _resolversMap.values().iterator(); iter.hasNext();) {
2676            DependencyResolver resolver = (DependencyResolver)iter.next();
2677            ModuleEntry[] entries = resolver.listModules(new OrganisationEntry(resolver, org));
2678            if (entries != null) {
2679                for (int i = 0; i < entries.length; i++) {
2680                    if (entries[i] != null) {
2681                        mods.add(entries[i].getModule());
2682                    }
2683                }
2684            }
2685        }
2686        return (String JavaDoc[])mods.toArray(new String JavaDoc[mods.size()]);
2687    }
2688    public RevisionEntry[] listRevisionEntries(ModuleEntry module) {
2689        List JavaDoc entries = new ArrayList JavaDoc();
2690        for (Iterator JavaDoc iter = _resolversMap.values().iterator(); iter.hasNext();) {
2691            DependencyResolver resolver = (DependencyResolver)iter.next();
2692            entries.addAll(Arrays.asList(resolver.listRevisions(module)));
2693        }
2694        return (RevisionEntry[])entries.toArray(new RevisionEntry[entries.size()]);
2695    }
2696    public String JavaDoc[] listRevisions(String JavaDoc org, String JavaDoc module) {
2697        List JavaDoc revs = new ArrayList JavaDoc();
2698        for (Iterator JavaDoc iter = _resolversMap.values().iterator(); iter.hasNext();) {
2699            DependencyResolver resolver = (DependencyResolver)iter.next();
2700            RevisionEntry[] entries = resolver.listRevisions(new ModuleEntry(new OrganisationEntry(resolver, org), module));
2701            if (entries != null) {
2702                for (int i = 0; i < entries.length; i++) {
2703                    if (entries[i] != null) {
2704                        revs.add(entries[i].getRevision());
2705                    }
2706                }
2707            }
2708        }
2709        return (String JavaDoc[])revs.toArray(new String JavaDoc[revs.size()]);
2710    }
2711    
2712    /**
2713     * Returns true if the name should be ignored in listing
2714     * @param name
2715     * @return
2716     */

2717    public boolean listingIgnore(String JavaDoc name) {
2718        return _listingIgnore.contains(name);
2719    }
2720    
2721    /**
2722     * Filters the names list by removing all names that should be ignored
2723     * as defined by the listing ignore list
2724     * @param names
2725     */

2726    public void filterIgnore(Collection JavaDoc names) {
2727        names.removeAll(_listingIgnore);
2728    }
2729    
2730    public boolean isCheckUpToDate() {
2731        return _checkUpToDate;
2732    }
2733    public void setCheckUpToDate(boolean checkUpToDate) {
2734        _checkUpToDate = checkUpToDate;
2735    }
2736
2737    public String JavaDoc getCacheArtifactPattern() {
2738        return _cacheArtifactPattern;
2739    }
2740    
2741
2742    public void setCacheArtifactPattern(String JavaDoc cacheArtifactPattern) {
2743        _cacheArtifactPattern = cacheArtifactPattern;
2744    }
2745    
2746
2747    public String JavaDoc getCacheIvyPattern() {
2748        return _cacheIvyPattern;
2749    }
2750    
2751
2752    public void setCacheIvyPattern(String JavaDoc cacheIvyPattern) {
2753        _cacheIvyPattern = cacheIvyPattern;
2754    }
2755
2756    public boolean doValidate() {
2757        return _validate;
2758    }
2759
2760    public void setValidate(boolean validate) {
2761        _validate = validate;
2762    }
2763
2764    public String JavaDoc getVariable(String JavaDoc name) {
2765        String JavaDoc val = (String JavaDoc)_variables.get(name);
2766        return val==null?val:substitute(val);
2767    }
2768
2769    public ConflictManager getDefaultConflictManager() {
2770        if (_defaultConflictManager == null) {
2771            _defaultConflictManager = new LatestConflictManager(getDefaultLatestStrategy());
2772        }
2773        return _defaultConflictManager;
2774    }
2775    
2776
2777    public void setDefaultConflictManager(ConflictManager defaultConflictManager) {
2778        _defaultConflictManager = defaultConflictManager;
2779    }
2780    
2781
2782    public LatestStrategy getDefaultLatestStrategy() {
2783        if (_defaultLatestStrategy == null) {
2784            _defaultLatestStrategy = new LatestRevisionStrategy();
2785        }
2786        return _defaultLatestStrategy;
2787    }
2788    
2789
2790    public void setDefaultLatestStrategy(LatestStrategy defaultLatestStrategy) {
2791        _defaultLatestStrategy = defaultLatestStrategy;
2792    }
2793
2794    private EventListenerList JavaDoc _listeners = new EventListenerList JavaDoc();
2795
2796    private boolean _logNotConvertedExclusionRule;
2797
2798    private Boolean JavaDoc _debugConflictResolution;
2799
2800    private VersionMatcher _versionMatcher;
2801
2802    public void addTransferListener(TransferListener listener) {
2803        _listeners.add(TransferListener.class, listener);
2804    }
2805
2806    public void removeTransferListener(TransferListener listener) {
2807        _listeners.remove(TransferListener.class, listener);
2808    }
2809
2810    public boolean hasTransferListener(TransferListener listener) {
2811        return Arrays.asList(_listeners.getListeners(TransferListener.class)).contains(listener);
2812    }
2813    protected void fireTransferEvent(TransferEvent evt) {
2814        Object JavaDoc[] listeners = _listeners.getListenerList();
2815        for (int i = listeners.length-2; i>=0; i-=2) {
2816            if (listeners[i]==TransferListener.class) {
2817                ((TransferListener)listeners[i+1]).transferProgress(evt);
2818            }
2819        }
2820    }
2821    
2822    public void addTrigger(Trigger trigger) {
2823        addIvyListener(trigger, trigger.getEventFilter());
2824    }
2825
2826    public void addConfigured(Trigger trigger) {
2827        addTrigger(trigger);
2828    }
2829
2830    public void addIvyListener(IvyListener listener) {
2831        _listeners.add(IvyListener.class, listener);
2832    }
2833
2834    public void addIvyListener(IvyListener listener, String JavaDoc eventName) {
2835        addIvyListener(listener, new IvyEventFilter(eventName, null, null));
2836    }
2837
2838    public void addIvyListener(IvyListener listener, Filter filter) {
2839        _listeners.add(IvyListener.class, new FilteredIvyListener(listener, filter));
2840    }
2841
2842    public void removeIvyListener(IvyListener listener) {
2843        _listeners.remove(IvyListener.class, listener);
2844        IvyListener[] listeners = (IvyListener[])_listeners.getListeners(IvyListener.class);
2845        for (int i = 0; i < listeners.length; i++) {
2846            if (listeners[i] instanceof FilteredIvyListener) {
2847                if (listener.equals(((FilteredIvyListener)listeners[i]).getIvyListener())) {
2848                    _listeners.remove(IvyListener.class, listeners[i]);
2849                }
2850            }
2851        }
2852    }
2853
2854    public boolean hasIvyListener(IvyListener listener) {
2855        return Arrays.asList(_listeners.getListeners(IvyListener.class)).contains(listener);
2856    }
2857    public void fireIvyEvent(IvyEvent evt) {
2858        Object JavaDoc[] listeners = _listeners.getListenerList();
2859        for (int i = listeners.length-2; i>=0; i-=2) {
2860            if (listeners[i]==IvyListener.class) {
2861                ((IvyListener)listeners[i+1]).progress(evt);
2862            }
2863        }
2864    }
2865
2866    public void transferProgress(TransferEvent evt) {
2867        fireTransferEvent(evt);
2868        fireIvyEvent(evt);
2869    }
2870
2871    public boolean isUseRemoteConfig() {
2872        return _useRemoteConfig;
2873    }
2874
2875    public void setUseRemoteConfig(boolean useRemoteConfig) {
2876        _useRemoteConfig = useRemoteConfig;
2877    }
2878
2879    public DependencyResolver getDictatorResolver() {
2880        return _dictatorResolver;
2881    }
2882
2883    public void setDictatorResolver(DependencyResolver dictatorResolver) {
2884        _dictatorResolver = dictatorResolver;
2885    }
2886
2887    /**
2888     * WARNING: Replace all current ivy variables by the given Map.
2889     * Should be used only when restoring variables.
2890     *
2891     * Thr given Map is not copied, but stored by reference.
2892     * @param variables
2893     */

2894    public void setVariables(Map JavaDoc variables) {
2895        if (variables == null) {
2896            throw new NullPointerException JavaDoc("variables shouldn't be null");
2897        }
2898        _variables = variables;
2899    }
2900
2901    public static URL JavaDoc getDefaultConfigurationURL() {
2902        return Ivy.class.getResource("conf/ivyconf.xml");
2903    }
2904
2905    /**
2906     * Saves the information of which resolver was used to resolve a md,
2907     * so that this info can be retrieve later (even after a jvm restart)
2908     * by getSavedResolverName(ModuleDescriptor md)
2909     * @param md the module descriptor resolved
2910     * @param name resolver name
2911     */

2912    public void saveResolver(File JavaDoc cache, ModuleDescriptor md, String JavaDoc name) {
2913        PropertiesFile cdf = getCachedDataFile(cache, md);
2914        cdf.setProperty("resolver", name);
2915        cdf.save();
2916    }
2917
2918    /**
2919     * Saves the information of which resolver was used to resolve a md,
2920     * so that this info can be retrieve later (even after a jvm restart)
2921     * by getSavedArtResolverName(ModuleDescriptor md)
2922     * @param md the module descriptor resolved
2923     * @param name artifact resolver name
2924     */

2925    public void saveArtResolver(File JavaDoc cache, ModuleDescriptor md, String JavaDoc name) {
2926        PropertiesFile cdf = getCachedDataFile(cache, md);
2927        cdf.setProperty("artifact.resolver", name);
2928        cdf.save();
2929    }
2930    
2931    public void saveArtifactOrigin(File JavaDoc cache, Artifact artifact, ArtifactOrigin origin) {
2932       PropertiesFile cdf = getCachedDataFile(cache, artifact.getModuleRevisionId());
2933       cdf.setProperty("artifact." + artifact.getName() + "#" + artifact.getExt() + ".is-local", String.valueOf(origin.isLocal()));
2934       cdf.setProperty("artifact." + artifact.getName() + "#" + artifact.getExt() + ".location", origin.getLocation());
2935       cdf.save();
2936    }
2937    
2938    public ArtifactOrigin getSavedArtifactOrigin(File JavaDoc cache, Artifact artifact) {
2939        PropertiesFile cdf = getCachedDataFile(cache, artifact.getModuleRevisionId());
2940        String JavaDoc location = cdf.getProperty("artifact." + artifact.getName() + "#" + artifact.getExt() + ".location");
2941        boolean isLocal = Boolean.valueOf(cdf.getProperty("artifact." + artifact.getName() + "#" + artifact.getExt() + ".is-local")).booleanValue();
2942        
2943        if (location == null) {
2944           // origin has not been specified, return null
2945
return null;
2946        }
2947        
2948        return new ArtifactOrigin(isLocal, location);
2949    }
2950    
2951    public void removeSavedArtifactOrigin(File JavaDoc cache, Artifact artifact) {
2952        PropertiesFile cdf = getCachedDataFile(cache, artifact.getModuleRevisionId());
2953        cdf.remove("artifact." + artifact.getName() + "#" + artifact.getExt() + ".location");
2954        cdf.remove("artifact." + artifact.getName() + "#" + artifact.getExt() + ".is-local");
2955        cdf.save();
2956    }
2957    
2958    private String JavaDoc getSavedResolverName(File JavaDoc cache, ModuleDescriptor md) {
2959        PropertiesFile cdf = getCachedDataFile(cache, md);
2960        return cdf.getProperty("resolver");
2961    }
2962
2963    private String JavaDoc getSavedArtResolverName(File JavaDoc cache, ModuleDescriptor md) {
2964        PropertiesFile cdf = getCachedDataFile(cache, md);
2965        return cdf.getProperty("artifact.resolver");
2966    }
2967
2968    private PropertiesFile getCachedDataFile(File JavaDoc cache, ModuleDescriptor md) {
2969       return getCachedDataFile(cache, md.getResolvedModuleRevisionId());
2970    }
2971    
2972    private PropertiesFile getCachedDataFile(File JavaDoc cache, ModuleRevisionId mRevId) {
2973        return new PropertiesFile(new File JavaDoc(cache, IvyPatternHelper.substitute(getCacheDataFilePattern(),mRevId)), "ivy cached data file for "+mRevId);
2974    }
2975
2976    public String JavaDoc getCacheDataFilePattern() {
2977        return _cacheDataFilePattern;
2978    }
2979
2980    public boolean logModuleWhenFound() {
2981        String JavaDoc var = getVariable("ivy.log.module.when.found");
2982        return var == null || Boolean.valueOf(var).booleanValue();
2983    }
2984
2985    public boolean logResolvedRevision() {
2986        String JavaDoc var = getVariable("ivy.log.resolved.revision");
2987        return var == null || Boolean.valueOf(var).booleanValue();
2988    }
2989
2990    public boolean debugConflictResolution() {
2991        if (_debugConflictResolution == null) {
2992            String JavaDoc var = getVariable("ivy.log.conflict.resolution");
2993            _debugConflictResolution = Boolean.valueOf(var != null && Boolean.valueOf(var).booleanValue());
2994        }
2995        return _debugConflictResolution.booleanValue();
2996    }
2997
2998    public boolean logNotConvertedExclusionRule() {
2999        return _logNotConvertedExclusionRule;
3000    }
3001    public void setLogNotConvertedExclusionRule(boolean logNotConvertedExclusionRule) {
3002        _logNotConvertedExclusionRule = logNotConvertedExclusionRule;
3003    }
3004    public StatusManager getStatusManager() {
3005        if (_statusManager == null) {
3006            _statusManager = StatusManager.newDefaultInstance();
3007        }
3008        return _statusManager;
3009    }
3010    public void setStatusManager(StatusManager statusManager) {
3011        _statusManager = statusManager;
3012    }
3013
3014    
3015    private static class ModuleSettings {
3016        private String JavaDoc _resolverName;
3017        private String JavaDoc _branch;
3018        private String JavaDoc _conflictManager;
3019        public ModuleSettings(String JavaDoc resolverName, String JavaDoc branch, String JavaDoc conflictManager) {
3020            _resolverName = resolverName;
3021            _branch = branch;
3022            _conflictManager = conflictManager;
3023        }
3024        public String JavaDoc toString() {
3025            return _resolverName != null ? "resolver: "+_resolverName:""
3026                    +_branch != null ? "branch: "+_branch:"";
3027        }
3028        public String JavaDoc getBranch() {
3029            return _branch;
3030        }
3031        public String JavaDoc getResolverName() {
3032            return _resolverName;
3033        }
3034        protected String JavaDoc getConflictManager() {
3035            return _conflictManager;
3036        }
3037    }
3038
3039
3040    public synchronized boolean isInterrupted() {
3041        return _interrupted;
3042    }
3043
3044
3045    /**
3046     * List module ids of the module accessible through the current resolvers
3047     * matching the given mid criteria according to the given matcher.
3048     *
3049     * @param criteria
3050     * @param matcher
3051     * @return
3052     */

3053    public ModuleId[] listModules(ModuleId criteria, PatternMatcher matcher) {
3054        List JavaDoc ret = new ArrayList JavaDoc();
3055        Matcher orgMatcher = matcher.getMatcher(criteria.getOrganisation());
3056        Matcher modMatcher = matcher.getMatcher(criteria.getName());
3057        Map JavaDoc tokenValues = new HashMap JavaDoc();
3058        String JavaDoc[] orgs = listTokenValues(IvyPatternHelper.ORGANISATION_KEY, tokenValues);
3059        for (int i = 0; i < orgs.length; i++) {
3060            if (orgMatcher.matches(orgs[i])) {
3061                tokenValues.put(IvyPatternHelper.ORGANISATION_KEY, orgs[i]);
3062                String JavaDoc[] mods = listTokenValues(IvyPatternHelper.MODULE_KEY, tokenValues);
3063                for (int j = 0; j < mods.length; j++) {
3064                    if (modMatcher.matches(mods[j])) {
3065                        ret.add(new ModuleId(orgs[i], mods[j]));
3066                    }
3067                }
3068            }
3069        }
3070        return (ModuleId[]) ret.toArray(new ModuleId[ret.size()]);
3071    }
3072    
3073    
3074    /**
3075     * List module revision ids of the module accessible through the current resolvers
3076     * matching the given mrid criteria according to the given matcher.
3077     *
3078     * @param criteria
3079     * @param matcher
3080     * @return
3081     */

3082    public ModuleRevisionId[] listModules(ModuleRevisionId criteria, PatternMatcher matcher) {
3083        List JavaDoc ret = new ArrayList JavaDoc();
3084        Matcher orgMatcher = matcher.getMatcher(criteria.getOrganisation());
3085        Matcher modMatcher = matcher.getMatcher(criteria.getName());
3086        Matcher branchMatcher = matcher.getMatcher(criteria.getBranch());
3087        Matcher revMatcher = matcher.getMatcher(criteria.getRevision());
3088        Map JavaDoc tokenValues = new HashMap JavaDoc();
3089        String JavaDoc[] orgs = listTokenValues(IvyPatternHelper.ORGANISATION_KEY, tokenValues);
3090        for (int i = 0; i < orgs.length; i++) {
3091            if (orgMatcher.matches(orgs[i])) {
3092                tokenValues.put(IvyPatternHelper.ORGANISATION_KEY, orgs[i]);
3093                String JavaDoc[] mods = listTokenValues(IvyPatternHelper.MODULE_KEY, tokenValues);
3094                for (int j = 0; j < mods.length; j++) {
3095                    if (modMatcher.matches(mods[j])) {
3096                        tokenValues.put(IvyPatternHelper.MODULE_KEY, mods[j]);
3097                        String JavaDoc[] branches = listTokenValues(IvyPatternHelper.BRANCH_KEY, tokenValues);
3098                        if (branches == null || branches.length == 0) {
3099                            branches = new String JavaDoc[] {getDefaultBranch(new ModuleId(orgs[i], mods[j]))};
3100                        }
3101                        for (int k = 0; k < branches.length; k++) {
3102                            if (branchMatcher.matches(branches[k])) {
3103                                tokenValues.put(IvyPatternHelper.BRANCH_KEY, tokenValues);
3104                                String JavaDoc[] revs = listTokenValues(IvyPatternHelper.REVISION_KEY, tokenValues);
3105                                for (int l = 0; l < revs.length; l++) {
3106                                    if (revMatcher.matches(revs[l])) {
3107                                        ret.add(ModuleRevisionId.newInstance(orgs[i], mods[j], branches[k], revs[l]));
3108                                    }
3109                                }
3110                            }
3111                        }
3112                    }
3113                }
3114            }
3115        }
3116        return (ModuleRevisionId[]) ret.toArray(new ModuleRevisionId[ret.size()]);
3117    }
3118
3119}
3120
Popular Tags