KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fr > jayasoft > ivy > resolver > BasicResolver


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.resolver;
7
8 import java.io.File JavaDoc;
9 import java.io.IOException JavaDoc;
10 import java.net.MalformedURLException JavaDoc;
11 import java.net.URL JavaDoc;
12 import java.text.ParseException JavaDoc;
13 import java.text.SimpleDateFormat JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.Collections JavaDoc;
17 import java.util.Date JavaDoc;
18 import java.util.HashMap JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.ListIterator JavaDoc;
22 import java.util.Map JavaDoc;
23
24 import fr.jayasoft.ivy.Artifact;
25 import fr.jayasoft.ivy.ArtifactOrigin;
26 import fr.jayasoft.ivy.DefaultArtifact;
27 import fr.jayasoft.ivy.DefaultModuleDescriptor;
28 import fr.jayasoft.ivy.DefaultModuleRevision;
29 import fr.jayasoft.ivy.DependencyDescriptor;
30 import fr.jayasoft.ivy.DependencyResolver;
31 import fr.jayasoft.ivy.Ivy;
32 import fr.jayasoft.ivy.IvyNode;
33 import fr.jayasoft.ivy.ModuleDescriptor;
34 import fr.jayasoft.ivy.ModuleId;
35 import fr.jayasoft.ivy.ModuleRevisionId;
36 import fr.jayasoft.ivy.ResolveData;
37 import fr.jayasoft.ivy.ResolvedModuleRevision;
38 import fr.jayasoft.ivy.event.download.EndArtifactDownloadEvent;
39 import fr.jayasoft.ivy.event.download.NeedArtifactEvent;
40 import fr.jayasoft.ivy.event.download.StartArtifactDownloadEvent;
41 import fr.jayasoft.ivy.parser.ModuleDescriptorParser;
42 import fr.jayasoft.ivy.parser.ModuleDescriptorParserRegistry;
43 import fr.jayasoft.ivy.report.ArtifactDownloadReport;
44 import fr.jayasoft.ivy.report.DownloadReport;
45 import fr.jayasoft.ivy.report.DownloadStatus;
46 import fr.jayasoft.ivy.repository.Resource;
47 import fr.jayasoft.ivy.repository.ResourceHelper;
48 import fr.jayasoft.ivy.repository.url.URLRepository;
49 import fr.jayasoft.ivy.repository.url.URLResource;
50 import fr.jayasoft.ivy.util.ChecksumHelper;
51 import fr.jayasoft.ivy.util.IvyPatternHelper;
52 import fr.jayasoft.ivy.util.Message;
53 import fr.jayasoft.ivy.xml.XmlModuleDescriptorParser;
54 import fr.jayasoft.ivy.xml.XmlModuleDescriptorWriter;
55
56 /**
57  * @author Xavier Hanin
58  *
59  */

60 public abstract class BasicResolver extends AbstractResolver {
61     public static final SimpleDateFormat JavaDoc DATE_FORMAT = new SimpleDateFormat JavaDoc("yyyyMMddHHmmss");
62
63     protected String JavaDoc _workspaceName;
64     /**
65      * True if the files resolved are dependent of the environment from which they have been resolved, false otherwise. In general, relative paths are dependent of the environment, and absolute paths including machine reference are not.
66      */

67     private boolean _envDependent = true;
68
69     private List JavaDoc _ivyattempts = new ArrayList JavaDoc();
70     private Map JavaDoc _artattempts = new HashMap JavaDoc();
71
72     private Boolean JavaDoc _checkmodified = null;
73
74     private boolean _checkconsistency = true;
75
76     private boolean _allownomd = true;
77     
78     private String JavaDoc _checksums = null;
79
80     private URLRepository _extartifactrep = new URLRepository(); // used only to download external artifacts
81

82     public BasicResolver() {
83         _workspaceName = Ivy.getLocalHostName();
84     }
85
86     public String JavaDoc getWorkspaceName() {
87         return _workspaceName;
88     }
89
90     public void setWorkspaceName(String JavaDoc workspaceName) {
91         _workspaceName = workspaceName;
92     }
93
94     public boolean isEnvDependent() {
95         return _envDependent;
96     }
97
98     public void setEnvDependent(boolean envDependent) {
99         _envDependent = envDependent;
100     }
101
102     /**
103      * True if this resolver should check lastmodified date to know if ivy files are up to date.
104      * @return
105      */

106     public boolean isCheckmodified() {
107         if (_checkmodified == null) {
108             if (getIvy() != null) {
109                 String JavaDoc check = getIvy().getVariable("ivy.resolver.default.check.modified");
110                 return check != null ? Boolean.valueOf(check).booleanValue() : false;
111             } else {
112                 return false;
113             }
114         } else {
115             return _checkmodified.booleanValue();
116         }
117     }
118     
119
120     public void setCheckmodified(boolean check) {
121         _checkmodified = Boolean.valueOf(check);
122     }
123     
124     public ResolvedModuleRevision getDependency(DependencyDescriptor dd, ResolveData data) throws ParseException JavaDoc {
125         DependencyDescriptor systemDd = dd;
126         dd = fromSystem(dd);
127         
128         clearIvyAttempts();
129         boolean downloaded = false;
130         boolean searched = false;
131         ModuleRevisionId mrid = dd.getDependencyRevisionId();
132         // check revision
133
int index = mrid.getRevision().indexOf("@");
134         if (index != -1 && !mrid.getRevision().substring(index+1).equals(_workspaceName)) {
135             Message.verbose("\t"+getName()+": unhandled revision => "+mrid.getRevision());
136             return null;
137         }
138         
139         boolean isDynamic = getIvy().getVersionMatcher().isDynamic(mrid);
140         if (isDynamic && !acceptLatest()) {
141             Message.error("dynamic revisions not handled by "+getClass().getName()+". impossible to resolve "+mrid);
142             return null;
143         }
144         
145         boolean isChangingRevision = getChangingMatcher().matches(mrid.getRevision());
146         boolean isChangingDependency = isChangingRevision || dd.isChanging();
147
148         // if we do not have to check modified and if the revision is exact and not changing,
149
// we first search for it in cache
150
ResolvedModuleRevision cachedRmr = null;
151         boolean checkedCache = false;
152         if (!isDynamic && !isCheckmodified() && !isChangingDependency) {
153             cachedRmr = findModuleInCache(data, mrid);
154             checkedCache = true;
155             if (cachedRmr != null) {
156                 if (cachedRmr.getDescriptor().isDefault() && cachedRmr.getResolver() != this) {
157                     Message.verbose("\t"+getName()+": found revision in cache: "+mrid+" (resolved by "+cachedRmr.getResolver().getName()+"): but it's a default one, maybe we can find a better one");
158                 } else {
159                     Message.verbose("\t"+getName()+": revision in cache: "+mrid);
160                     return toSystem(cachedRmr);
161                 }
162             }
163         }
164         checkInterrupted();
165         URL JavaDoc cachedIvyURL = null;
166         ResolvedResource ivyRef = findIvyFileRef(dd, data);
167         checkInterrupted();
168         searched = true;
169         
170         // get module descriptor
171
ModuleDescriptorParser parser;
172         ModuleDescriptor md;
173         ModuleDescriptor systemMd = null;
174         if (ivyRef == null) {
175             if (!isAllownomd()) {
176                 Message.verbose("\t"+getName()+": no ivy file found for "+mrid);
177                 logIvyNotFound(mrid);
178                 return null;
179             }
180             parser = XmlModuleDescriptorParser.getInstance();
181             md = DefaultModuleDescriptor.newDefaultInstance(mrid, dd.getAllDependencyArtifactsIncludes());
182             ResolvedResource artifactRef = findFirstArtifactRef(md, dd, data);
183             if (getIvy() != null && getIvy().isInterrupted()) {
184                 throw new RuntimeException JavaDoc("interrupted");
185             }
186             if (artifactRef == null) {
187                 Message.verbose("\t"+getName()+": no ivy file nor artifact found for "+mrid);
188                 logIvyNotFound(mrid);
189                 String JavaDoc[] conf = md.getConfigurationsNames();
190                 for (int i = 0; i < conf.length; i++) {
191                     Artifact[] artifacts = md.getArtifacts(conf[i]);
192                     for (int j = 0; j < artifacts.length; j++) {
193                         logArtifactNotFound(artifacts[j]);
194                     }
195                 }
196                 if (!checkedCache) {
197                     cachedRmr = findModuleInCache(data, mrid);
198                 }
199                 if (cachedRmr != null) {
200                     Message.verbose("\t"+getName()+": revision in cache: "+mrid);
201                     return toSystem(cachedRmr);
202                 }
203                 return null;
204             } else {
205                 Message.verbose("\t"+getName()+": no ivy file found for "+mrid+": using default data");
206                 logIvyNotFound(mrid);
207                 if (isDynamic) {
208                     md.setResolvedModuleRevisionId(ModuleRevisionId.newInstance(mrid, artifactRef.getRevision()));
209                 }
210             }
211         } else {
212             ResolvedModuleRevision rmr = null;
213             if (ivyRef instanceof MDResolvedResource) {
214                 rmr = ((MDResolvedResource)ivyRef).getResolvedModuleRevision();
215             }
216             if (rmr == null) {
217                 rmr = parse(ivyRef, dd, data);
218                 if (rmr == null) {
219                     return null;
220                 }
221             }
222             if (!rmr.isDownloaded()) {
223                 return toSystem(rmr);
224             } else {
225                 md = rmr.getDescriptor();
226                 parser = ModuleDescriptorParserRegistry.getInstance().getParser(ivyRef.getResource());
227                 cachedIvyURL = rmr.getLocalMDUrl();
228                 
229                 // check descriptor data is in sync with resource revision and names
230
systemMd = toSystem(md);
231                 if (_checkconsistency) {
232                     checkDescriptorConsistency(mrid, md, ivyRef);
233                     checkDescriptorConsistency(systemDd.getDependencyRevisionId(), systemMd, ivyRef);
234                 } else {
235                     if (md instanceof DefaultModuleDescriptor) {
236                         String JavaDoc revision = getRevision(ivyRef, mrid, md);
237                         ((DefaultModuleDescriptor)md).setModuleRevisionId(ModuleRevisionId.newInstance(mrid, revision));
238                     } else {
239                         Message.warn("consistency disabled with instance of non DefaultModuleDescriptor... module info can't be updated, so consistency check will be done");
240                         checkDescriptorConsistency(mrid, md, ivyRef);
241                         checkDescriptorConsistency(systemDd.getDependencyRevisionId(), systemMd, ivyRef);
242                     }
243                 }
244             }
245         }
246         
247         if (systemMd == null) {
248             systemMd = toSystem(md);
249         }
250         
251         // resolve revision
252
ModuleRevisionId resolvedMrid = mrid;
253         if (isDynamic) {
254             resolvedMrid = md.getResolvedModuleRevisionId();
255             if (resolvedMrid.getRevision() == null || resolvedMrid.getRevision().length() == 0) {
256                 if (ivyRef.getRevision() == null || ivyRef.getRevision().length() == 0) {
257                     resolvedMrid = ModuleRevisionId.newInstance(resolvedMrid, "working@"+getName());
258                 } else {
259                     resolvedMrid = ModuleRevisionId.newInstance(resolvedMrid, ivyRef.getRevision());
260                 }
261             }
262             Message.verbose("\t\t["+resolvedMrid.getRevision()+"] "+mrid.getModuleId());
263         }
264         md.setResolvedModuleRevisionId(resolvedMrid);
265         systemMd.setResolvedModuleRevisionId(toSystem(resolvedMrid)); // keep system md in sync with md
266

267         // check module descriptor revision
268
if (!getIvy().getVersionMatcher().accept(mrid, md)) {
269             Message.info("\t"+getName()+": unacceptable revision => was="+md.getModuleRevisionId().getRevision()+" required="+mrid.getRevision());
270             return null;
271         }
272         
273         
274         // resolve and check publication date
275
if (data.getDate() != null) {
276             long pubDate = getPublicationDate(md, dd, data);
277             if (pubDate > data.getDate().getTime()) {
278                 Message.info("\t"+getName()+": unacceptable publication date => was="+new Date JavaDoc(pubDate)+" required="+data.getDate());
279                 return null;
280             } else if (pubDate == -1) {
281                 Message.info("\t"+getName()+": impossible to guess publication date: artifact missing for "+mrid);
282                 return null;
283             }
284             md.setResolvedPublicationDate(new Date JavaDoc(pubDate));
285             systemMd.setResolvedPublicationDate(new Date JavaDoc(pubDate)); // keep system md in sync with md
286
}
287     
288         try {
289             File JavaDoc ivyFile = data.getIvy().getIvyFileInCache(data.getCache(), systemMd.getResolvedModuleRevisionId());
290             if (ivyRef == null) {
291                 // a basic ivy file is written containing default data
292
XmlModuleDescriptorWriter.write(systemMd, ivyFile);
293             } else {
294                 if (md instanceof DefaultModuleDescriptor) {
295                     DefaultModuleDescriptor dmd = (DefaultModuleDescriptor)md;
296                     if (data.getIvy().logNotConvertedExclusionRule() && dmd.isNamespaceUseful()) {
297                         Message.warn("the module descriptor "+ivyRef.getResource()+" has information which can't be converted into the system namespace. It will require the availability of the namespace '"+getNamespace().getName()+"' to be fully usable.");
298                     }
299                 }
300                 // copy and update ivy file from source to cache
301
parser.toIvyFile(cachedIvyURL.openStream(), ivyRef.getResource(), ivyFile, systemMd);
302                 long repLastModified = ivyRef.getLastModified();
303                 if (repLastModified > 0) {
304                     ivyFile.setLastModified(repLastModified);
305                 }
306             }
307         } catch (Exception JavaDoc e) {
308             if (ivyRef == null) {
309                 Message.warn("impossible to create ivy file in cache for module : " + resolvedMrid);
310             } else {
311                 e.printStackTrace();
312                 Message.warn("impossible to copy ivy file to cache : "+ivyRef.getResource());
313             }
314         }
315         
316         data.getIvy().saveResolver(data.getCache(), systemMd, getName());
317         data.getIvy().saveArtResolver(data.getCache(), systemMd, getName());
318         return new DefaultModuleRevision(this, this, systemMd, searched, downloaded, cachedIvyURL);
319     }
320
321     private String JavaDoc getRevision(ResolvedResource ivyRef, ModuleRevisionId askedMrid, ModuleDescriptor md) throws ParseException JavaDoc {
322         String JavaDoc revision = ivyRef.getRevision();
323         if (revision == null) {
324             Message.debug("no revision found in reference for "+askedMrid);
325             if (getIvy().getVersionMatcher().isDynamic(askedMrid)) {
326                 if (md.getModuleRevisionId().getRevision() == null) {
327                     return "working@"+getName();
328                 } else {
329                     Message.debug("using "+askedMrid);
330                     revision = md.getModuleRevisionId().getRevision();
331                 }
332             } else {
333                 Message.debug("using "+askedMrid);
334                 revision = askedMrid.getRevision();
335             }
336         }
337         return revision;
338     }
339     
340     public ResolvedModuleRevision parse(
341             ResolvedResource ivyRef,
342             DependencyDescriptor dd,
343             ResolveData data
344             ) throws ParseException JavaDoc {
345         
346         ModuleRevisionId mrid = dd.getDependencyRevisionId();
347         ModuleDescriptorParser parser = ModuleDescriptorParserRegistry.getInstance().getParser(ivyRef.getResource());
348         if (parser == null) {
349             Message.warn("no module descriptor parser available for "+ivyRef.getResource());
350             return null;
351         }
352         Message.verbose("\t"+getName()+": found md file for "+mrid);
353         Message.verbose("\t\t=> "+ivyRef);
354         Message.debug("\tparser = "+parser);
355
356         boolean isChangingRevision = getChangingMatcher().matches(mrid.getRevision());
357         boolean isChangingDependency = isChangingRevision || dd.isChanging();
358         Date JavaDoc cachedPublicationDate = null;
359         ModuleRevisionId resolvedMrid = mrid;
360         
361         // first check if this dependency has not yet been resolved
362
if (getIvy().getVersionMatcher().isDynamic(mrid)) {
363             resolvedMrid = ModuleRevisionId.newInstance(mrid, ivyRef.getRevision());
364             IvyNode node = getSystemNode(data, resolvedMrid);
365             if (node != null && node.getModuleRevision() != null) {
366                 // this revision has already be resolved : return it
367
if (node.getDescriptor() != null && node.getDescriptor().isDefault()) {
368                     Message.verbose("\t"+getName()+": found already resolved revision: "+resolvedMrid+": but it's a default one, maybe we can find a better one");
369                 } else {
370                     Message.verbose("\t"+getName()+": revision already resolved: "+resolvedMrid);
371                     return searchedRmr(node.getModuleRevision());
372                 }
373             }
374         }
375         
376         // now let's see if we can find it in cache and if it is up to date
377
ResolvedModuleRevision rmr = findModuleInCache(data, resolvedMrid);
378         if (rmr != null) {
379             if (rmr.getDescriptor().isDefault() && rmr.getResolver() != this) {
380                 Message.verbose("\t"+getName()+": found revision in cache: "+mrid+" (resolved by "+rmr.getResolver().getName()+"): but it's a default one, maybe we can find a better one");
381             } else {
382                 if (!isCheckmodified() && !isChangingDependency) {
383                     Message.verbose("\t"+getName()+": revision in cache: "+mrid);
384                     return searchedRmr(rmr);
385                 }
386                 long repLastModified = ivyRef.getLastModified();
387                 long cacheLastModified = rmr.getDescriptor().getLastModified();
388                 if (!rmr.getDescriptor().isDefault() && repLastModified <= cacheLastModified) {
389                     Message.verbose("\t"+getName()+": revision in cache (not updated): "+resolvedMrid);
390                     return searchedRmr(rmr);
391                 } else {
392                     Message.verbose("\t"+getName()+": revision in cache is not up to date: "+resolvedMrid);
393                     if (isChangingDependency) {
394                         // ivy file has been updated, we should see if it has a new publication date
395
// to see if a new download is required (in case the dependency is a changing one)
396
cachedPublicationDate = rmr.getDescriptor().getResolvedPublicationDate();
397                     }
398                 }
399             }
400         }
401         
402         // now download ivy file and parse it
403
URL JavaDoc cachedIvyURL = null;
404         File JavaDoc ivyTempFile = null;
405         try {
406             // first check if source file is not cache file itself
407
if (ResourceHelper.equals(ivyRef.getResource(),
408                     data.getIvy().getIvyFileInCache(data.getCache(), toSystem(resolvedMrid)))) {
409                 Message.error("invalid configuration for resolver '"+getName()+"': pointing ivy files to ivy cache is forbidden !");
410                 return null;
411             }
412             
413             // temp file is used to prevent downloading twice
414
ivyTempFile = File.createTempFile("ivy", "xml");
415             ivyTempFile.deleteOnExit();
416             Message.debug("\t"+getName()+": downloading "+ivyRef.getResource()+" to "+ivyTempFile);
417             getAndCheck(ivyRef.getResource(), ivyTempFile);
418             try {
419                 cachedIvyURL = ivyTempFile.toURL();
420             } catch (MalformedURLException JavaDoc ex) {
421                 Message.warn("malformed url exception for temp file: "+ivyTempFile+": "+ex.getMessage());
422                 return null;
423             }
424         } catch (IOException JavaDoc ex) {
425             Message.warn("problem while downloading ivy file: "+ivyRef.getResource()+" to "+ivyTempFile+": "+ex.getMessage());
426             return null;
427         }
428         try {
429             ModuleDescriptor md = parser.parseDescriptor(data.getIvy(), cachedIvyURL, ivyRef.getResource(), doValidate(data));
430             Message.debug("\t"+getName()+": parsed downloaded md file for "+mrid+" parsed="+md.getModuleRevisionId());
431             
432             
433             // check if we should delete old artifacts
434
boolean deleteOldArtifacts = false;
435             if (cachedPublicationDate != null && !cachedPublicationDate.equals(md.getResolvedPublicationDate())) {
436                 // artifacts have changed, they should be downloaded again
437
Message.verbose(dd+" has changed: deleting old artifacts");
438                 deleteOldArtifacts = true;
439             }
440             if (deleteOldArtifacts) {
441                 String JavaDoc[] confs = rmr.getDescriptor().getConfigurationsNames();
442                 for (int i = 0; i < confs.length; i++) {
443                     Artifact[] arts = rmr.getDescriptor().getArtifacts(confs[i]);
444                     for (int j = 0; j < arts.length; j++) {
445                         Artifact transformedArtifact = toSystem(arts[j]);
446                         ArtifactOrigin origin = data.getIvy().getSavedArtifactOrigin(data.getCache(), transformedArtifact);
447                         File JavaDoc artFile = data.getIvy().getArchiveFileInCache(data.getCache(), transformedArtifact, origin, false);
448                         if (artFile.exists()) {
449                             Message.debug("deleting "+artFile);
450                             artFile.delete();
451                         }
452                         data.getIvy().removeSavedArtifactOrigin(data.getCache(), transformedArtifact);
453                     }
454                 }
455             } else if (isChangingDependency){
456                 Message.verbose(dd+" is changing, but has not changed: will trust cached artifacts if any");
457             }
458             return new DefaultModuleRevision(this, this, md, true, true, cachedIvyURL);
459         } catch (IOException JavaDoc ex) {
460             Message.warn("io problem while parsing ivy file: "+ivyRef.getResource()+": "+ex.getMessage());
461             return null;
462         }
463         
464     }
465
466     protected ResourceMDParser getRMDParser(final DependencyDescriptor dd, final ResolveData data) {
467         return new ResourceMDParser() {
468             public MDResolvedResource parse(Resource resource, String JavaDoc rev) {
469                 try {
470                     ResolvedModuleRevision rmr = BasicResolver.this.parse(new ResolvedResource(resource, rev), dd, data);
471                     if (rmr == null) {
472                         return null;
473                     } else {
474                         return new MDResolvedResource(resource, rev, rmr);
475                     }
476                 } catch (ParseException JavaDoc e) {
477                     return null;
478                 }
479             }
480             
481         };
482     }
483
484     protected ResourceMDParser getDefaultRMDParser(final ModuleId mid) {
485         return new ResourceMDParser() {
486             public MDResolvedResource parse(Resource resource, String JavaDoc rev) {
487                 return new MDResolvedResource(resource, rev, new DefaultModuleRevision(BasicResolver.this, BasicResolver.this, DefaultModuleDescriptor.newDefaultInstance(new ModuleRevisionId(mid, rev)), false, false, null));
488             }
489         };
490     }
491
492
493 // private boolean isResolved(ResolveData data, ModuleRevisionId mrid) {
494
// IvyNode node = getSystemNode(data, mrid);
495
// return node != null && node.getModuleRevision() != null;
496
// }
497
//
498
private void checkDescriptorConsistency(ModuleRevisionId mrid, ModuleDescriptor md, ResolvedResource ivyRef) throws ParseException JavaDoc {
499         boolean ok = true;
500         StringBuffer JavaDoc errors = new StringBuffer JavaDoc();
501         if (!mrid.getOrganisation().equals(md.getModuleRevisionId().getOrganisation())) {
502             Message.error("\t"+getName()+": bad organisation found in "+ivyRef.getResource()+": expected='"+mrid.getOrganisation()+"' found='"+md.getModuleRevisionId().getOrganisation()+"'");
503             errors.append("bad organisation: expected='"+mrid.getOrganisation()+"' found='"+md.getModuleRevisionId().getOrganisation()+"'; ");
504             ok = false;
505         }
506         if (!mrid.getName().equals(md.getModuleRevisionId().getName())) {
507             Message.error("\t"+getName()+": bad module name found in "+ivyRef.getResource()+": expected='"+mrid.getName()+" found='"+md.getModuleRevisionId().getName()+"'");
508             errors.append("bad module name: expected='"+mrid.getName()+"' found='"+md.getModuleRevisionId().getName()+"'; ");
509             ok = false;
510         }
511         if (ivyRef.getRevision() != null && !ivyRef.getRevision().startsWith("working@")) {
512             ModuleRevisionId expectedMrid = ModuleRevisionId.newInstance(mrid, ivyRef.getRevision());
513             if (!getIvy().getVersionMatcher().accept(expectedMrid, md)) {
514                 Message.error("\t"+getName()+": bad revision found in "+ivyRef.getResource()+": expected='"+ivyRef.getRevision()+" found='"+md.getModuleRevisionId().getRevision()+"'");
515                 errors.append("bad revision: expected='"+ivyRef.getRevision()+"' found='"+md.getModuleRevisionId().getRevision()+"'; ");
516                 ok = false;
517             }
518         }
519         if (!getIvy().getStatusManager().isStatus(md.getStatus())) {
520             Message.error("\t"+getName()+": bad status found in "+ivyRef.getResource()+": '"+md.getStatus()+"'");
521             errors.append("bad status: '"+md.getStatus()+"'; ");
522             ok = false;
523         }
524         if (!ok) {
525             throw new ParseException JavaDoc("inconsistent module descriptor file found in '"+ivyRef.getResource()+"': "+errors, 0);
526         }
527     }
528
529     protected void clearIvyAttempts() {
530         _ivyattempts.clear();
531         clearArtifactAttempts();
532     }
533
534     protected ResolvedModuleRevision searchedRmr(final ResolvedModuleRevision rmr) {
535         // delegate all to previously found except isSearched
536
return new ResolvedModuleRevision() {
537             public boolean isSearched() {
538                 return true;
539             }
540         
541             public boolean isDownloaded() {
542                 return rmr.isDownloaded();
543             }
544         
545             public ModuleDescriptor getDescriptor() {
546                 return rmr.getDescriptor();
547             }
548         
549             public Date JavaDoc getPublicationDate() {
550                 return rmr.getPublicationDate();
551             }
552         
553             public ModuleRevisionId getId() {
554                 return rmr.getId();
555             }
556         
557             public DependencyResolver getResolver() {
558                 return rmr.getResolver();
559             }
560
561             public DependencyResolver getArtifactResolver() {
562                 return rmr.getArtifactResolver();
563             }
564             public URL JavaDoc getLocalMDUrl() {
565                 return rmr.getLocalMDUrl();
566             }
567         };
568     }
569     
570     protected void logIvyAttempt(String JavaDoc attempt) {
571         _ivyattempts.add(attempt);
572         Message.verbose("\t\ttried "+attempt);
573     }
574     
575     protected void logArtifactAttempt(Artifact art, String JavaDoc attempt) {
576         List JavaDoc attempts = (List JavaDoc)_artattempts.get(art);
577         if (attempts == null) {
578             attempts = new ArrayList JavaDoc();
579             _artattempts.put(art, attempts);
580         }
581         attempts.add(attempt);
582         Message.verbose("\t\ttried "+attempt);
583     }
584     
585     public void reportFailure() {
586         for (ListIterator JavaDoc iter = _ivyattempts.listIterator(); iter.hasNext();) {
587             String JavaDoc m = (String JavaDoc)iter.next();
588             Message.warn("\t\t"+getName()+": tried "+m);
589         }
590         for (Iterator JavaDoc iter = _artattempts.keySet().iterator(); iter.hasNext();) {
591             Artifact art = (Artifact)iter.next();
592             List JavaDoc attempts = (List JavaDoc)_artattempts.get(art);
593             if (attempts != null) {
594                 Message.warn("\t\t"+getName()+": tried artifact "+art+":");
595                 for (ListIterator JavaDoc iterator = attempts.listIterator(); iterator.hasNext();) {
596                     String JavaDoc m = (String JavaDoc)iterator.next();
597                     Message.warn("\t\t\t"+m);
598                 }
599             }
600         }
601     }
602
603     public void reportFailure(Artifact art) {
604         List JavaDoc attempts = (List JavaDoc)_artattempts.get(art);
605         if (attempts != null) {
606             for (ListIterator JavaDoc iter = attempts.listIterator(); iter.hasNext();) {
607                 String JavaDoc m = (String JavaDoc)iter.next();
608                 Message.warn("\t\t"+getName()+": tried "+m);
609             }
610         }
611     }
612
613     protected boolean acceptLatest() {
614         return true;
615     }
616
617     public DownloadReport download(Artifact[] artifacts, Ivy ivy, File JavaDoc cache, boolean useOrigin) {
618         clearArtifactAttempts();
619         DownloadReport dr = new DownloadReport();
620         for (int i = 0; i < artifacts.length; i++) {
621             final ArtifactDownloadReport adr = new ArtifactDownloadReport(artifacts[i]);
622             dr.addArtifactReport(adr);
623             ivy.fireIvyEvent(new NeedArtifactEvent(ivy, this, artifacts[i]));
624             ArtifactOrigin origin = ivy.getSavedArtifactOrigin(cache, artifacts[i]);
625             // if we can use origin file, we just ask ivy for the file in cache, and it will return
626
// the original one if possible. If we are not in useOrigin mode, we use the getArchivePath
627
// method which always return a path in the actual cache
628
File JavaDoc archiveFile = ivy.getArchiveFileInCache(cache, artifacts[i], origin, useOrigin);
629                     
630             if (archiveFile.exists()) {
631                 Message.verbose("\t[NOT REQUIRED] "+artifacts[i]);
632                 adr.setDownloadStatus(DownloadStatus.NO);
633                 adr.setSize(archiveFile.length());
634                 adr.setArtifactOrigin(origin);
635             } else {
636                 Artifact artifact = fromSystem(artifacts[i]);
637                 if (!artifact.equals(artifacts[i])) {
638                     Message.verbose("\t"+getName()+"looking for artifact "+artifact+ " (is "+artifacts[i]+" in system namespace)");
639                 }
640                 long start = System.currentTimeMillis();
641                 try {
642                     ResolvedResource artifactRef = getArtifactRef(artifact, null);
643                     if (artifactRef != null) {
644                         origin = new ArtifactOrigin(artifactRef.getResource().isLocal(), artifactRef.getResource().getName());
645                         if (useOrigin && artifactRef.getResource().isLocal()) {
646                             Message.verbose("\t[NOT REQUIRED] "+artifacts[i]);
647                             ivy.saveArtifactOrigin(cache, artifacts[i], origin);
648                             archiveFile = ivy.getArchiveFileInCache(cache, artifacts[i], origin);
649                             adr.setDownloadStatus(DownloadStatus.NO);
650                             adr.setSize(archiveFile.length());
651                             adr.setArtifactOrigin(origin);
652                         } else {
653                             // refresh archive file now that we better now its origin
654
archiveFile = ivy.getArchiveFileInCache(cache, artifacts[i], origin, useOrigin);
655                             if (ResourceHelper.equals(artifactRef.getResource(),
656                                     archiveFile)) {
657                                 Message.error("invalid configuration for resolver '"+getName()+"': pointing artifacts to ivy cache is forbidden !");
658                                 return null;
659                             }
660                             Message.info("downloading "+artifactRef.getResource()+" ...");
661                             ivy.fireIvyEvent(new StartArtifactDownloadEvent(ivy, this, artifacts[i], origin));
662
663                             File JavaDoc tmp = ivy.getArchiveFileInCache(cache,
664                                     new DefaultArtifact(
665                                             artifacts[i].getModuleRevisionId(),
666                                             artifacts[i].getPublicationDate(),
667                                             artifacts[i].getName(),
668                                             artifacts[i].getType(),
669                                             artifacts[i].getExt()+".part",
670                                             artifacts[i].getExtraAttributes()),
671                                             origin, useOrigin);
672
673                             // deal with artifact with url special case
674
if (artifactRef.getResource().getName().equals(String.valueOf(artifacts[i].getUrl()))) {
675                                 Message.verbose("\t"+getName()+": downloading "+artifactRef.getResource().getName());
676                                 Message.debug("\t\tto "+tmp);
677                                 if (tmp.getParentFile() != null) {
678                                     tmp.getParentFile().mkdirs();
679                                 }
680                                 _extartifactrep.get(artifactRef.getResource().getName(), tmp);
681                                 adr.setSize(tmp.length());
682                             } else {
683                                 adr.setSize(getAndCheck(artifactRef.getResource(), tmp));
684                             }
685                             if (!tmp.renameTo(archiveFile)) {
686                                 Message.warn("\t[FAILED ] "+artifacts[i]+" impossible to move temp file to definitive one ("+(System.currentTimeMillis()-start)+"ms)");
687                                 adr.setDownloadStatus(DownloadStatus.FAILED);
688                             } else {
689                                 ivy.saveArtifactOrigin(cache, artifacts[i], origin);
690                                 Message.info("\t[SUCCESSFUL ] "+artifacts[i]+" ("+(System.currentTimeMillis()-start)+"ms)");
691                                 adr.setDownloadStatus(DownloadStatus.SUCCESSFUL);
692                                 adr.setArtifactOrigin(origin);
693                             }
694                         }
695                     } else {
696                         logArtifactNotFound(artifacts[i]);
697                         adr.setDownloadStatus(DownloadStatus.FAILED);
698                     }
699                 } catch (Exception JavaDoc ex) {
700                     Message.warn("\t[FAILED ] "+artifacts[i]+" : "+ex.getMessage()+" ("+(System.currentTimeMillis()-start)+"ms)");
701                     adr.setDownloadStatus(DownloadStatus.FAILED);
702                 }
703                 checkInterrupted();
704             }
705             ivy.fireIvyEvent(new EndArtifactDownloadEvent(ivy, this, artifacts[i], adr, archiveFile));
706         }
707         return dr;
708     }
709
710     protected void clearArtifactAttempts() {
711         _artattempts.clear();
712     }
713     
714     public boolean exists(Artifact artifact) {
715         ResolvedResource artifactRef = getArtifactRef(artifact, null);
716         if (artifactRef != null) {
717             return artifactRef.getResource().exists();
718         }
719         return false;
720     }
721
722     protected long getPublicationDate(ModuleDescriptor md, DependencyDescriptor dd, ResolveData data) {
723         if (md.getPublicationDate() != null) {
724             return md.getPublicationDate().getTime();
725         }
726         ResolvedResource artifactRef = findFirstArtifactRef(md, dd, data);
727         if (artifactRef != null) {
728             return artifactRef.getLastModified();
729         }
730         return -1;
731     }
732
733     public String JavaDoc toString() {
734         return getName();
735     }
736     
737     public String JavaDoc[] listTokenValues(String JavaDoc token, Map JavaDoc otherTokenValues) {
738         Collection JavaDoc ret = findNames(otherTokenValues, token);
739         return (String JavaDoc[]) ret.toArray(new String JavaDoc[ret.size()]);
740     }
741
742     public OrganisationEntry[] listOrganisations() {
743         Collection JavaDoc names = findNames(Collections.EMPTY_MAP, IvyPatternHelper.ORGANISATION_KEY);
744         OrganisationEntry[] ret = new OrganisationEntry[names.size()];
745         int i =0;
746         for (Iterator JavaDoc iter = names.iterator(); iter.hasNext(); i++) {
747             String JavaDoc org = (String JavaDoc)iter.next();
748             ret[i] = new OrganisationEntry(this, org);
749         }
750         return ret;
751     }
752
753     public ModuleEntry[] listModules(OrganisationEntry org) {
754         Map JavaDoc tokenValues = new HashMap JavaDoc();
755         tokenValues.put(IvyPatternHelper.ORGANISATION_KEY, org.getOrganisation());
756         Collection JavaDoc names = findNames(tokenValues, IvyPatternHelper.MODULE_KEY);
757         ModuleEntry[] ret = new ModuleEntry[names.size()];
758         int i =0;
759         for (Iterator JavaDoc iter = names.iterator(); iter.hasNext(); i++) {
760             String JavaDoc name = (String JavaDoc)iter.next();
761             ret[i] = new ModuleEntry(org, name);
762         }
763         return ret;
764     }
765
766     public RevisionEntry[] listRevisions(ModuleEntry mod) {
767         Map JavaDoc tokenValues = new HashMap JavaDoc();
768         tokenValues.put(IvyPatternHelper.ORGANISATION_KEY, mod.getOrganisation());
769         tokenValues.put(IvyPatternHelper.MODULE_KEY, mod.getModule());
770         Collection JavaDoc names = findNames(tokenValues, IvyPatternHelper.REVISION_KEY);
771         RevisionEntry[] ret = new RevisionEntry[names.size()];
772         int i =0;
773         for (Iterator JavaDoc iter = names.iterator(); iter.hasNext(); i++) {
774             String JavaDoc name = (String JavaDoc)iter.next();
775             ret[i] = new RevisionEntry(mod, name);
776         }
777         return ret;
778     }
779
780     protected abstract Collection JavaDoc findNames(Map JavaDoc tokenValues, String JavaDoc token);
781
782     protected abstract ResolvedResource findIvyFileRef(DependencyDescriptor dd, ResolveData data);
783
784     protected ResolvedResource findFirstArtifactRef(ModuleDescriptor md, DependencyDescriptor dd, ResolveData data) {
785         ResolvedResource ret = null;
786         String JavaDoc[] conf = md.getConfigurationsNames();
787         for (int i = 0; i < conf.length; i++) {
788             Artifact[] artifacts = md.getArtifacts(conf[i]);
789             for (int j = 0; j < artifacts.length; j++) {
790                 ret = getArtifactRef(artifacts[j], data.getDate());
791                 if (ret != null) {
792                     return ret;
793                 }
794             }
795         }
796         return null;
797     }
798
799     protected long getAndCheck(Resource resource, File JavaDoc dest) throws IOException JavaDoc {
800         long size = get(resource, dest);
801         String JavaDoc[] checksums = getChecksumAlgorithms();
802         boolean checked = false;
803         for (int i = 0; i < checksums.length && !checked; i++) {
804             checked = check(resource, dest, checksums[i]);
805         }
806         return size;
807     }
808
809     private boolean check(Resource resource, File JavaDoc dest, String JavaDoc algorithm) throws IOException JavaDoc {
810         Resource csRes = resource.clone(resource.getName()+"."+algorithm);
811         if (csRes.exists()) {
812             Message.debug(algorithm + " file found for "+resource+": checking...");
813             File JavaDoc csFile = File.createTempFile("ivytmp", algorithm);
814             try {
815                 get(csRes, csFile);
816                 if (!ChecksumHelper.check(dest, csFile, algorithm)) {
817                     dest.delete();
818                     throw new IOException JavaDoc("invalid "+algorithm);
819                 } else {
820                     Message.verbose(algorithm + " OK for "+resource);
821                     return true;
822                 }
823             } finally {
824                 csFile.delete();
825             }
826         } else {
827             return false;
828         }
829     }
830
831
832     protected ResolvedResource getArtifactRef(Artifact artifact, Date JavaDoc date) {
833         ResolvedResource ret = findArtifactRef(artifact, date);
834         if (ret == null && artifact.getUrl() != null) {
835             URL JavaDoc url = artifact.getUrl();
836             Message.verbose("\tusing url for "+artifact+": "+url);
837             ret = new ResolvedResource(new URLResource(url), artifact.getModuleRevisionId().getRevision());
838         }
839         return ret;
840     }
841
842     protected abstract ResolvedResource findArtifactRef(Artifact artifact, Date JavaDoc date);
843
844     protected abstract long get(Resource resource, File JavaDoc dest) throws IOException JavaDoc;
845
846     protected abstract void logIvyNotFound(ModuleRevisionId mrid);
847
848     protected abstract void logArtifactNotFound(Artifact artifact);
849
850     public boolean isCheckconsistency() {
851         return _checkconsistency;
852     }
853
854     public void setCheckconsistency(boolean checkConsitency) {
855         _checkconsistency = checkConsitency;
856     }
857
858     public boolean isAllownomd() {
859         return _allownomd;
860     }
861     public void setAllownomd(boolean b) {
862         _allownomd = b;
863     }
864
865     public String JavaDoc[] getChecksumAlgorithms() {
866         String JavaDoc csDef = _checksums == null ? getIvy().getVariable("ivy.checksums") : _checksums;
867         if (csDef == null) {
868             return new String JavaDoc[0];
869         }
870         // csDef is a comma separated list of checksum algorithms to use with this resolver
871
// we parse and return it as a String[]
872
String JavaDoc[] checksums = csDef.split(",");
873         List JavaDoc algos = new ArrayList JavaDoc();
874         for (int i = 0; i < checksums.length; i++) {
875             String JavaDoc cs = checksums[i].trim();
876             if (!"".equals(cs) && !"none".equals(cs)) {
877                 algos.add(cs);
878             }
879         }
880         return (String JavaDoc[]) algos.toArray(new String JavaDoc[algos.size()]);
881     }
882
883     public void setChecksums(String JavaDoc checksums) {
884         _checksums = checksums;
885     }
886
887 }
888
Popular Tags