~ubuntu-branches/ubuntu/trusty/ivy/trusty

« back to all changes in this revision

Viewing changes to src/java/org/apache/ivy/core/cache/DefaultRepositoryCacheManager.java

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath
  • Date: 2009-03-06 22:04:56 UTC
  • Revision ID: james.westby@ubuntu.com-20090306220456-5v37luqiuqda8ewp
Tags: upstream-2.0.0
ImportĀ upstreamĀ versionĀ 2.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 
3
 *  contributor license agreements.  See the NOTICE file distributed with
 
4
 *  this work for additional information regarding copyright ownership.
 
5
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 
6
 *  (the "License"); you may not use this file except in compliance with
 
7
 *  the License.  You may obtain a copy of the License at
 
8
 *
 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
 
10
 *
 
11
 *  Unless required by applicable law or agreed to in writing, software
 
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
 
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
 *  See the License for the specific language governing permissions and
 
15
 *  limitations under the License.
 
16
 *
 
17
 */
 
18
package org.apache.ivy.core.cache;
 
19
 
 
20
import java.io.File;
 
21
import java.io.IOException;
 
22
import java.text.ParseException;
 
23
import java.util.Date;
 
24
import java.util.Map;
 
25
import java.util.regex.Pattern;
 
26
 
 
27
import org.apache.ivy.core.IvyPatternHelper;
 
28
import org.apache.ivy.core.module.descriptor.Artifact;
 
29
import org.apache.ivy.core.module.descriptor.DefaultArtifact;
 
30
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
 
31
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
 
32
import org.apache.ivy.core.module.id.ModuleRevisionId;
 
33
import org.apache.ivy.core.module.id.ModuleRules;
 
34
import org.apache.ivy.core.report.ArtifactDownloadReport;
 
35
import org.apache.ivy.core.report.DownloadStatus;
 
36
import org.apache.ivy.core.report.MetadataArtifactDownloadReport;
 
37
import org.apache.ivy.core.resolve.ResolvedModuleRevision;
 
38
import org.apache.ivy.core.settings.IvySettings;
 
39
import org.apache.ivy.plugins.IvySettingsAware;
 
40
import org.apache.ivy.plugins.lock.LockStrategy;
 
41
import org.apache.ivy.plugins.matcher.ExactPatternMatcher;
 
42
import org.apache.ivy.plugins.matcher.MapMatcher;
 
43
import org.apache.ivy.plugins.matcher.Matcher;
 
44
import org.apache.ivy.plugins.matcher.NoMatcher;
 
45
import org.apache.ivy.plugins.matcher.PatternMatcher;
 
46
import org.apache.ivy.plugins.namespace.NameSpaceHelper;
 
47
import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
 
48
import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry;
 
49
import org.apache.ivy.plugins.parser.ParserSettings;
 
50
import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser;
 
51
import org.apache.ivy.plugins.repository.ArtifactResourceResolver;
 
52
import org.apache.ivy.plugins.repository.ResourceDownloader;
 
53
import org.apache.ivy.plugins.repository.ResourceHelper;
 
54
import org.apache.ivy.plugins.resolver.DependencyResolver;
 
55
import org.apache.ivy.plugins.resolver.util.ResolvedResource;
 
56
import org.apache.ivy.util.Checks;
 
57
import org.apache.ivy.util.FileUtil;
 
58
import org.apache.ivy.util.Message;
 
59
import org.apache.ivy.util.PropertiesFile;
 
60
 
 
61
public class DefaultRepositoryCacheManager implements RepositoryCacheManager, IvySettingsAware {
 
62
    private static final String DEFAULT_ARTIFACT_PATTERN =
 
63
        "[organisation]/[module](/[branch])/[type]s/[artifact]-[revision](-[classifier])(.[ext])";
 
64
 
 
65
    private static final String DEFAULT_DATA_FILE_PATTERN = 
 
66
        "[organisation]/[module](/[branch])/ivydata-[revision].properties";
 
67
 
 
68
    private static final String DEFAULT_IVY_PATTERN = 
 
69
        "[organisation]/[module](/[branch])/ivy-[revision].xml";
 
70
    
 
71
    private static final int DEFAULT_MEMORY_CACHE_SIZE = 150;
 
72
    
 
73
    private IvySettings settings;
 
74
    
 
75
    private File basedir;
 
76
 
 
77
    private LockStrategy lockStrategy;
 
78
 
 
79
    private String name;
 
80
 
 
81
    private String ivyPattern; 
 
82
 
 
83
    private String dataFilePattern = DEFAULT_DATA_FILE_PATTERN; 
 
84
    
 
85
    private String artifactPattern;
 
86
 
 
87
    private String lockStrategyName; 
 
88
 
 
89
    private String changingPattern;
 
90
 
 
91
    private String changingMatcherName = PatternMatcher.EXACT_OR_REGEXP;
 
92
 
 
93
    private Boolean checkmodified;
 
94
 
 
95
    private Boolean useOrigin;
 
96
    
 
97
    private ModuleRules/*<Long>*/ ttlRules = new ModuleRules();
 
98
 
 
99
    private Long defaultTTL = null;
 
100
 
 
101
    private ModuleDescriptorMemoryCache memoryModuleDescrCache;
 
102
 
 
103
    public DefaultRepositoryCacheManager() {
 
104
    }
 
105
 
 
106
    public DefaultRepositoryCacheManager(String name, IvySettings settings, File basedir) {
 
107
        setName(name);
 
108
        setSettings(settings);
 
109
        setBasedir(basedir);
 
110
    }
 
111
 
 
112
    public IvySettings getSettings() {
 
113
        return settings;
 
114
    }
 
115
 
 
116
    public void setSettings(IvySettings settings) {
 
117
        this.settings = settings;
 
118
    }
 
119
 
 
120
    public File getIvyFileInCache(ModuleRevisionId mrid) {
 
121
        String file = IvyPatternHelper.substitute(getIvyPattern(), DefaultArtifact
 
122
                .newIvyArtifact(mrid, null));
 
123
        return new File(getRepositoryCacheRoot(), file);
 
124
    }
 
125
 
 
126
    public String getIvyPattern() {
 
127
        if (ivyPattern == null) {
 
128
            if (settings != null) {
 
129
                ivyPattern = settings.getDefaultCacheIvyPattern();
 
130
            }
 
131
            if (ivyPattern == null) {
 
132
                ivyPattern = DEFAULT_IVY_PATTERN;
 
133
            }
 
134
        }
 
135
        return ivyPattern;
 
136
    }
 
137
    
 
138
    public String getArtifactPattern() {
 
139
        if (artifactPattern == null) {
 
140
            if (settings != null) {
 
141
                artifactPattern = settings.getDefaultCacheArtifactPattern();
 
142
            }
 
143
            if (artifactPattern == null) {
 
144
                artifactPattern = DEFAULT_ARTIFACT_PATTERN;
 
145
            }
 
146
        }
 
147
        return artifactPattern;
 
148
    }
 
149
 
 
150
    public void setArtifactPattern(String artifactPattern) {
 
151
        CacheUtil.checkCachePattern(artifactPattern);
 
152
        this.artifactPattern = artifactPattern;
 
153
    }
 
154
 
 
155
    public File getBasedir() {
 
156
        if (basedir == null) {
 
157
            basedir = settings.getDefaultRepositoryCacheBasedir();
 
158
        }
 
159
        return basedir;
 
160
    }
 
161
 
 
162
    public void setBasedir(File cache) {
 
163
        this.basedir = cache;
 
164
    }
 
165
    
 
166
    public long getDefaultTTL() {
 
167
        if (defaultTTL == null) {
 
168
            defaultTTL = new Long(parseDuration(settings.getVariable("ivy.cache.ttl.default")));
 
169
        }
 
170
        return defaultTTL.longValue();
 
171
    }
 
172
    
 
173
    public void setDefaultTTL(long defaultTTL) {
 
174
        this.defaultTTL = new Long(defaultTTL);
 
175
    }
 
176
    
 
177
    public void setDefaultTTL(String defaultTTL) {
 
178
        this.defaultTTL = new Long(parseDuration(defaultTTL));
 
179
    }
 
180
 
 
181
    public String getDataFilePattern() {
 
182
        return dataFilePattern;
 
183
    }
 
184
 
 
185
    public void setDataFilePattern(String dataFilePattern) {
 
186
        CacheUtil.checkCachePattern(dataFilePattern);
 
187
        this.dataFilePattern = dataFilePattern;
 
188
    }
 
189
 
 
190
    public void setIvyPattern(String ivyPattern) {
 
191
        CacheUtil.checkCachePattern(ivyPattern);
 
192
        this.ivyPattern = ivyPattern;
 
193
    }
 
194
 
 
195
    public String getName() {
 
196
        return name;
 
197
    }
 
198
 
 
199
    public void setName(String name) {
 
200
        this.name = name;
 
201
    }
 
202
 
 
203
    public String getChangingMatcherName() {
 
204
        return changingMatcherName;
 
205
    }
 
206
 
 
207
    public void setChangingMatcher(String changingMatcherName) {
 
208
        this.changingMatcherName = changingMatcherName;
 
209
    }
 
210
 
 
211
    public String getChangingPattern() {
 
212
        return changingPattern;
 
213
    }
 
214
 
 
215
    public void setChangingPattern(String changingPattern) {
 
216
        this.changingPattern = changingPattern;
 
217
    }
 
218
 
 
219
    public void addTTL(Map attributes, PatternMatcher matcher, long duration) {
 
220
        ttlRules.defineRule(new MapMatcher(attributes, matcher), new Long(duration));
 
221
    }
 
222
    
 
223
    public void addConfiguredTtl(Map/*<String,String>*/ attributes) {
 
224
        String duration = (String) attributes.remove("duration");
 
225
        if (duration == null) {
 
226
            throw new IllegalArgumentException("'duration' attribute is mandatory for ttl");
 
227
        }
 
228
        String matcher = (String) attributes.remove("matcher");
 
229
        addTTL(
 
230
            attributes, 
 
231
            matcher == null ? ExactPatternMatcher.INSTANCE : settings.getMatcher(matcher), 
 
232
                    parseDuration(duration));
 
233
    }
 
234
 
 
235
    public void setMemorySize(int size) {
 
236
        memoryModuleDescrCache = new ModuleDescriptorMemoryCache(size);
 
237
    }
 
238
    
 
239
    public ModuleDescriptorMemoryCache getMemoryCache() {
 
240
        if (memoryModuleDescrCache == null) {
 
241
            memoryModuleDescrCache = new ModuleDescriptorMemoryCache(DEFAULT_MEMORY_CACHE_SIZE);
 
242
        }
 
243
        return memoryModuleDescrCache;
 
244
    }
 
245
    
 
246
    
 
247
    private static final Pattern DURATION_PATTERN 
 
248
        = Pattern.compile("(?:(\\d+)d)? ?(?:(\\d+)h)? ?(?:(\\d+)m)? ?(?:(\\d+)s)? ?(?:(\\d+)ms)?");
 
249
 
 
250
    private static final int MILLIS_IN_SECONDS = 1000; 
 
251
    private static final int MILLIS_IN_MINUTES = 60 * MILLIS_IN_SECONDS;
 
252
    private static final int MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTES;
 
253
    private static final int MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR;
 
254
 
 
255
    private long parseDuration(String duration) {
 
256
        if (duration == null) {
 
257
            return 0;
 
258
        }
 
259
        java.util.regex.Matcher m = DURATION_PATTERN.matcher(duration);
 
260
        if (m.matches()) {
 
261
            //CheckStyle:MagicNumber| OFF
 
262
            int days = getGroupIntValue(m, 1);
 
263
            int hours = getGroupIntValue(m, 2);
 
264
            int minutes = getGroupIntValue(m, 3);
 
265
            int seconds = getGroupIntValue(m, 4);
 
266
            int millis = getGroupIntValue(m, 5);
 
267
            //CheckStyle:MagicNumber| ON
 
268
            
 
269
            return days * MILLIS_IN_DAY 
 
270
            + hours * MILLIS_IN_HOUR
 
271
            + minutes * MILLIS_IN_MINUTES
 
272
            + seconds * MILLIS_IN_SECONDS
 
273
            + millis;
 
274
        } else {
 
275
            throw new IllegalArgumentException("invalid duration '" 
 
276
                + duration + "': it must match " + DURATION_PATTERN.pattern());
 
277
        }
 
278
    }
 
279
 
 
280
    private int getGroupIntValue(java.util.regex.Matcher m, int groupNumber) {
 
281
        String g = m.group(groupNumber);
 
282
        return g == null || g.length() == 0 ? 0 : Integer.parseInt(g);
 
283
    }
 
284
 
 
285
    /**
 
286
     * True if this cache should check lastmodified date to know if ivy files are up to date.
 
287
     * 
 
288
     * @return
 
289
     */
 
290
    public boolean isCheckmodified() {
 
291
        if (checkmodified == null) {
 
292
            if (getSettings() != null) {
 
293
                String check = getSettings().getVariable("ivy.resolver.default.check.modified");
 
294
                return check != null ? Boolean.valueOf(check).booleanValue() : false;
 
295
            } else {
 
296
                return false;
 
297
            }
 
298
        } else {
 
299
            return checkmodified.booleanValue();
 
300
        }
 
301
    }
 
302
 
 
303
    public void setCheckmodified(boolean check) {
 
304
        checkmodified = Boolean.valueOf(check);
 
305
    }
 
306
    
 
307
    /**
 
308
     * True if this cache should use artifacts original location when possible, false if they should
 
309
     * be copied to cache.
 
310
     */
 
311
    public boolean isUseOrigin() {
 
312
        if (useOrigin == null) {
 
313
            if (getSettings() != null) {
 
314
                return getSettings().isDefaultUseOrigin();
 
315
            } else {
 
316
                return false;
 
317
            }
 
318
        } else {
 
319
            return useOrigin.booleanValue();
 
320
        }
 
321
    }
 
322
 
 
323
    public void setUseOrigin(boolean b) {
 
324
        useOrigin = Boolean.valueOf(b);
 
325
    }
 
326
    
 
327
    /**
 
328
     * Returns a File object pointing to where the artifact can be found on the local file system.
 
329
     * This is usually in the cache, but it can be directly in the repository if it is local and if
 
330
     * the resolve has been done with useOrigin = true
 
331
     */
 
332
    public File getArchiveFileInCache(Artifact artifact) {
 
333
        ArtifactOrigin origin = getSavedArtifactOrigin(artifact);
 
334
        return getArchiveFileInCache(artifact, origin);
 
335
    }
 
336
 
 
337
    /**
 
338
     * Returns a File object pointing to where the artifact can be found on the local file system.
 
339
     * This is usually in the cache, but it can be directly in the repository if it is local and if
 
340
     * the resolve has been done with useOrigin = true
 
341
     */
 
342
    public File getArchiveFileInCache(Artifact artifact, ArtifactOrigin origin) {
 
343
        File archive = new File(getRepositoryCacheRoot(), getArchivePathInCache(artifact, origin));
 
344
        if (!archive.exists() 
 
345
                && !ArtifactOrigin.isUnknown(origin) && origin.isLocal()) {
 
346
            File original = Checks.checkAbsolute(
 
347
                origin.getLocation(), artifact + " origin location");
 
348
            if (original.exists()) {
 
349
                return original;
 
350
            }
 
351
        }
 
352
        return archive;
 
353
    }
 
354
 
 
355
    /**
 
356
     * Returns a File object pointing to where the artifact can be found on the local file system,
 
357
     * using or not the original location depending on the availability of origin information
 
358
     * provided as parameter and the setting of useOrigin. If useOrigin is false, this method will
 
359
     * always return the file in the cache.
 
360
     */
 
361
    private File getArchiveFileInCache(
 
362
            Artifact artifact, ArtifactOrigin origin, boolean useOrigin) {
 
363
        if (useOrigin && !ArtifactOrigin.isUnknown(origin) && origin.isLocal()) {
 
364
            return Checks.checkAbsolute(origin.getLocation(), artifact + " origin location");
 
365
        } else {
 
366
            return new File(getRepositoryCacheRoot(), getArchivePathInCache(artifact, origin));
 
367
        }
 
368
    }
 
369
 
 
370
    public String getArchivePathInCache(Artifact artifact) {
 
371
        return IvyPatternHelper.substitute(getArtifactPattern(), artifact);
 
372
    }
 
373
 
 
374
    public String getArchivePathInCache(Artifact artifact, ArtifactOrigin origin) {
 
375
        if (isOriginalMetadataArtifact(artifact)) {
 
376
            return IvyPatternHelper.substitute(getIvyPattern() + ".original", artifact, origin);
 
377
        } else {
 
378
            return IvyPatternHelper.substitute(getArtifactPattern(), artifact, origin);
 
379
        }
 
380
    }
 
381
 
 
382
    /**
 
383
     * Saves the information of which resolver was used to resolve a md, so that this info can be
 
384
     * retrieve later (even after a jvm restart) by getSavedResolverName(ModuleDescriptor md)
 
385
     * 
 
386
     * @param md
 
387
     *            the module descriptor resolved
 
388
     * @param name
 
389
     *            resolver name
 
390
     */
 
391
    private void saveResolver(ModuleDescriptor md, String name) {
 
392
        // should always be called with a lock on module metadata artifact
 
393
        PropertiesFile cdf = getCachedDataFile(md);
 
394
        cdf.setProperty("resolver", name);
 
395
        cdf.save();
 
396
    }
 
397
 
 
398
    /**
 
399
     * Saves the information of which resolver was used to resolve a md, so that this info can be
 
400
     * retrieve later (even after a jvm restart) by getSavedArtResolverName(ModuleDescriptor md)
 
401
     * 
 
402
     * @param md
 
403
     *            the module descriptor resolved
 
404
     * @param name
 
405
     *            artifact resolver name
 
406
     */
 
407
    public void saveResolvers(
 
408
            ModuleDescriptor md, String metadataResolverName, String artifactResolverName) {
 
409
        ModuleRevisionId mrid = md.getResolvedModuleRevisionId();
 
410
        if (!lockMetadataArtifact(mrid)) {
 
411
            Message.error("impossible to acquire lock for " + mrid);
 
412
            return;
 
413
        }
 
414
        try {
 
415
            PropertiesFile cdf = getCachedDataFile(md);
 
416
            cdf.setProperty("resolver", metadataResolverName);
 
417
            cdf.setProperty("artifact.resolver", artifactResolverName);
 
418
            cdf.save();
 
419
        } finally {
 
420
            unlockMetadataArtifact(mrid);
 
421
        }
 
422
    }
 
423
 
 
424
    private String getSavedResolverName(ModuleDescriptor md) {
 
425
        // should always be called with a lock on module metadata artifact
 
426
        PropertiesFile cdf = getCachedDataFile(md);
 
427
        return cdf.getProperty("resolver");
 
428
    }
 
429
 
 
430
    private String getSavedArtResolverName(ModuleDescriptor md) {
 
431
        // should always be called with a lock on module metadata artifact
 
432
        PropertiesFile cdf = getCachedDataFile(md);
 
433
        return cdf.getProperty("artifact.resolver");
 
434
    }
 
435
 
 
436
    void saveArtifactOrigin(Artifact artifact, ArtifactOrigin origin) {
 
437
        // should always be called with a lock on module metadata artifact
 
438
        PropertiesFile cdf = getCachedDataFile(artifact.getModuleRevisionId());
 
439
        cdf.setProperty(getIsLocalKey(artifact), String.valueOf(origin.isLocal()));
 
440
        cdf.setProperty(getLocationKey(artifact), origin.getLocation());
 
441
        cdf.save();
 
442
    }
 
443
 
 
444
    private void removeSavedArtifactOrigin(Artifact artifact) {
 
445
        // should always be called with a lock on module metadata artifact
 
446
        PropertiesFile cdf = getCachedDataFile(artifact.getModuleRevisionId());
 
447
        cdf.remove(getLocationKey(artifact));
 
448
        cdf.remove(getIsLocalKey(artifact));
 
449
        cdf.save();
 
450
    }
 
451
 
 
452
    public ArtifactOrigin getSavedArtifactOrigin(Artifact artifact) {
 
453
        ModuleRevisionId mrid = artifact.getModuleRevisionId();
 
454
        if (!lockMetadataArtifact(mrid)) {
 
455
            Message.error("impossible to acquire lock for " + mrid);
 
456
            return ArtifactOrigin.unkwnown(artifact);
 
457
        }
 
458
        try {
 
459
            PropertiesFile cdf = getCachedDataFile(artifact.getModuleRevisionId());
 
460
            String location = cdf.getProperty(getLocationKey(artifact));
 
461
            String local = cdf.getProperty(getIsLocalKey(artifact));
 
462
            boolean isLocal = Boolean.valueOf(local).booleanValue();
 
463
 
 
464
            if (location == null) {
 
465
                // origin has not been specified, return null
 
466
                return ArtifactOrigin.unkwnown(artifact);
 
467
            }
 
468
 
 
469
            return new ArtifactOrigin(artifact, isLocal, location);
 
470
        } finally {
 
471
            unlockMetadataArtifact(mrid);
 
472
        }
 
473
    }
 
474
 
 
475
    /**
 
476
     * Creates the unique prefix key that will reference the artifact within the properties.
 
477
     * 
 
478
     * @param artifact
 
479
     *            the artifact to create the unique key from. Cannot be null.
 
480
     * @return the unique prefix key as a string.
 
481
     */
 
482
    private String getPrefixKey(Artifact artifact) {
 
483
        // use the hashcode as a uuid for the artifact (fingers crossed)
 
484
        int hashCode = artifact.getId().hashCode();
 
485
        // use just some visual cue
 
486
        return "artifact:" + artifact.getName() + "#" + artifact.getType() + "#"
 
487
                + artifact.getExt() + "#" + hashCode;
 
488
    }
 
489
 
 
490
    /**
 
491
     * Returns the key used to identify the location of the artifact.
 
492
     * 
 
493
     * @param artifact
 
494
     *            the artifact to generate the key from. Cannot be null.
 
495
     * @return the key to be used to reference the artifact location.
 
496
     */
 
497
    private String getLocationKey(Artifact artifact) {
 
498
        String prefix = getPrefixKey(artifact);
 
499
        return prefix + ".location";
 
500
    }
 
501
 
 
502
    /**
 
503
     * Returns the key used to identify if the artifact is local.
 
504
     * 
 
505
     * @param artifact
 
506
     *            the artifact to generate the key from. Cannot be null.
 
507
     * @return the key to be used to reference the artifact location.
 
508
     */
 
509
    private String getIsLocalKey(Artifact artifact) {
 
510
        String prefix = getPrefixKey(artifact);
 
511
        return prefix + ".is-local";
 
512
    }
 
513
 
 
514
    private PropertiesFile getCachedDataFile(ModuleDescriptor md) {
 
515
        return getCachedDataFile(md.getResolvedModuleRevisionId());
 
516
    }
 
517
 
 
518
    private PropertiesFile getCachedDataFile(ModuleRevisionId mRevId) {
 
519
        return new PropertiesFile(new File(getRepositoryCacheRoot(), 
 
520
            IvyPatternHelper.substitute(
 
521
                getDataFilePattern(), mRevId)), "ivy cached data file for " + mRevId);
 
522
    }
 
523
 
 
524
    public ResolvedModuleRevision findModuleInCache(
 
525
            DependencyDescriptor dd, ModuleRevisionId requestedRevisionId, 
 
526
            CacheMetadataOptions options, String expectedResolver) {
 
527
        ModuleRevisionId mrid = requestedRevisionId;
 
528
        if (isCheckmodified(dd, requestedRevisionId, options)) {
 
529
            Message.verbose("don't use cache for " + mrid + ": checkModified=true");
 
530
            return null;
 
531
        }
 
532
        if (isChanging(dd, requestedRevisionId, options)) {
 
533
            Message.verbose("don't use cache for " + mrid + ": changing=true");
 
534
            return null;
 
535
        }
 
536
        return doFindModuleInCache(mrid, options, expectedResolver);
 
537
    }
 
538
 
 
539
    private ResolvedModuleRevision doFindModuleInCache(
 
540
            ModuleRevisionId mrid, CacheMetadataOptions options, String expectedResolver) {
 
541
        if (!lockMetadataArtifact(mrid)) {
 
542
            Message.error("impossible to acquire lock for " + mrid);
 
543
            return null;
 
544
        }
 
545
        try {
 
546
            if (settings.getVersionMatcher().isDynamic(mrid)) {
 
547
                String resolvedRevision = getResolvedRevision(mrid, options);
 
548
                if (resolvedRevision != null) {
 
549
                    Message.verbose("found resolved revision in cache: " 
 
550
                        + mrid + " => " + resolvedRevision);
 
551
                    mrid = ModuleRevisionId.newInstance(mrid, resolvedRevision);
 
552
                } else {
 
553
                    return null;
 
554
                }
 
555
            }
 
556
 
 
557
            File ivyFile = getIvyFileInCache(mrid);
 
558
            if (ivyFile.exists()) {
 
559
                // found in cache !
 
560
                try {
 
561
                    XmlModuleDescriptorParser parser = XmlModuleDescriptorParser.getInstance();
 
562
                    ModuleDescriptor depMD = getMdFromCache(parser, options, ivyFile);
 
563
                    String resolverName = getSavedResolverName(depMD);
 
564
                    String artResolverName = getSavedArtResolverName(depMD);
 
565
                    DependencyResolver resolver = settings.getResolver(resolverName);
 
566
                    if (resolver == null) {
 
567
                        Message.debug("\tresolver not found: " + resolverName
 
568
                            + " => trying to use the one configured for " + mrid);
 
569
                        resolver = settings.getResolver(depMD.getResolvedModuleRevisionId());
 
570
                        if (resolver != null) {
 
571
                            Message.debug("\tconfigured resolver found for "
 
572
                                + depMD.getResolvedModuleRevisionId() + ": "
 
573
                                + resolver.getName() + ": saving this data");
 
574
                            saveResolver(depMD, resolver.getName());
 
575
                        }
 
576
                    }
 
577
                    DependencyResolver artResolver = settings.getResolver(artResolverName);
 
578
                    if (artResolver == null) {
 
579
                        artResolver = resolver;
 
580
                    }
 
581
                    if (resolver != null) {
 
582
                        Message.debug("\tfound ivy file in cache for " + mrid + " (resolved by "
 
583
                            + resolver.getName() + "): " + ivyFile);
 
584
                        if (expectedResolver == null 
 
585
                                || expectedResolver.equals(resolver.getName())) {
 
586
                            MetadataArtifactDownloadReport madr 
 
587
                            = new MetadataArtifactDownloadReport(
 
588
                                depMD.getMetadataArtifact());
 
589
                            madr.setDownloadStatus(DownloadStatus.NO);
 
590
                            madr.setSearched(false);
 
591
                            madr.setLocalFile(ivyFile);
 
592
                            madr.setSize(ivyFile.length());
 
593
                            madr.setArtifactOrigin(
 
594
                                getSavedArtifactOrigin(depMD.getMetadataArtifact()));
 
595
                            return new ResolvedModuleRevision(
 
596
                                resolver, artResolver, depMD, madr);
 
597
                        } else {
 
598
                            Message.debug(
 
599
                                "found module in cache but with a different resolver: "
 
600
                                + "discarding: " + mrid 
 
601
                                + "; expected resolver=" + expectedResolver 
 
602
                                + "; resolver=" + resolver.getName());
 
603
                        }
 
604
                    } else {
 
605
                        Message.debug("\tresolver not found: " + resolverName
 
606
                            + " => cannot use cached ivy file for " + mrid);
 
607
                    }
 
608
                } catch (Exception e) {
 
609
                    // will try with resolver
 
610
                    Message.debug("\tproblem while parsing cached ivy file for: " + mrid + ": "
 
611
                        + e.getMessage());
 
612
                }
 
613
            } else {
 
614
                Message.debug("\tno ivy file in cache for " + mrid + ": tried " + ivyFile);
 
615
            }
 
616
        } finally {
 
617
            unlockMetadataArtifact(mrid);
 
618
        }
 
619
        return null;
 
620
    }
 
621
 
 
622
    
 
623
    private class MyModuleDescriptorProvider implements ModuleDescriptorProvider {
 
624
        
 
625
        private final ModuleDescriptorParser mdParser;
 
626
 
 
627
        public MyModuleDescriptorProvider(ModuleDescriptorParser mdParser) {
 
628
            this.mdParser = mdParser;            
 
629
        }
 
630
        
 
631
        public ModuleDescriptor provideModule(ParserSettings ivySettings, 
 
632
                File descriptorURL, boolean validate) throws ParseException, IOException {
 
633
            return mdParser.parseDescriptor(ivySettings, descriptorURL.toURI().toURL(), validate);
 
634
        }
 
635
    }
 
636
    
 
637
    private ModuleDescriptor getMdFromCache(XmlModuleDescriptorParser mdParser, 
 
638
            CacheMetadataOptions options, File ivyFile) 
 
639
            throws ParseException, IOException {
 
640
        ModuleDescriptorMemoryCache cache = getMemoryCache();
 
641
        ModuleDescriptorProvider mdProvider = new MyModuleDescriptorProvider(mdParser); 
 
642
        return cache.get(ivyFile, settings, options.isValidate(), mdProvider);
 
643
    }
 
644
 
 
645
    private ModuleDescriptor getStaledMd(ModuleDescriptorParser mdParser, 
 
646
            CacheMetadataOptions options, File ivyFile) 
 
647
            throws ParseException, IOException {
 
648
        ModuleDescriptorMemoryCache cache = getMemoryCache();
 
649
        ModuleDescriptorProvider mdProvider = new MyModuleDescriptorProvider(mdParser); 
 
650
        return cache.getStale(ivyFile, settings, options.isValidate(), mdProvider);
 
651
    }
 
652
 
 
653
    
 
654
    private String getResolvedRevision(ModuleRevisionId mrid, CacheMetadataOptions options) {
 
655
        if (!lockMetadataArtifact(mrid)) {
 
656
            Message.error("impossible to acquire lock for " + mrid);
 
657
            return null;
 
658
        }
 
659
        try {
 
660
            String resolvedRevision = null;
 
661
            if (options.isForce()) {
 
662
                Message.verbose("refresh mode: no check for cached resolved revision for " + mrid);
 
663
                return null;
 
664
            }
 
665
            PropertiesFile cachedResolvedRevision = getCachedDataFile(mrid);
 
666
            String expiration = cachedResolvedRevision.getProperty("expiration.time");
 
667
            if (expiration == null) {
 
668
                Message.verbose("no cached resolved revision for " + mrid);
 
669
                return null;
 
670
            } 
 
671
            if (System.currentTimeMillis() > Long.parseLong(expiration)) {
 
672
                Message.verbose("cached resolved revision expired for " + mrid);
 
673
                return null;
 
674
            }
 
675
            resolvedRevision = cachedResolvedRevision.getProperty("resolved.revision");
 
676
            if (resolvedRevision == null) {
 
677
                Message.verbose("no cached resolved revision value for " + mrid);
 
678
                return null;
 
679
            }
 
680
            return resolvedRevision;
 
681
        } finally {
 
682
            unlockMetadataArtifact(mrid);
 
683
        }
 
684
    }
 
685
 
 
686
    private void saveResolvedRevision(ModuleRevisionId mrid, String revision) {
 
687
        if (!lockMetadataArtifact(mrid)) {
 
688
            Message.error("impossible to acquire lock for " + mrid);
 
689
            return;
 
690
        }
 
691
        try {
 
692
            PropertiesFile cachedResolvedRevision = getCachedDataFile(mrid);
 
693
            cachedResolvedRevision.setProperty("expiration.time", getExpiration(mrid));
 
694
            cachedResolvedRevision.setProperty("resolved.revision", revision);
 
695
            cachedResolvedRevision.save();
 
696
        } finally {
 
697
            unlockMetadataArtifact(mrid);
 
698
        }
 
699
    }
 
700
 
 
701
    private String getExpiration(ModuleRevisionId mrid) {
 
702
        return String.valueOf(System.currentTimeMillis() + getTTL(mrid));
 
703
    }
 
704
 
 
705
    public long getTTL(ModuleRevisionId mrid) {
 
706
        Long ttl = (Long) ttlRules.getRule(mrid);
 
707
        return ttl == null ? getDefaultTTL() : ttl.longValue();
 
708
    }
 
709
 
 
710
    public String toString() {
 
711
        return name;
 
712
    }
 
713
 
 
714
    public File getRepositoryCacheRoot() {
 
715
        return getBasedir();
 
716
    }
 
717
 
 
718
    public LockStrategy getLockStrategy() {
 
719
        if (lockStrategy == null) {
 
720
            if (lockStrategyName != null) {
 
721
                lockStrategy = settings.getLockStrategy(lockStrategyName);
 
722
            } else {
 
723
                lockStrategy = settings.getDefaultLockStrategy();
 
724
            }
 
725
        }
 
726
        return lockStrategy;
 
727
    }
 
728
    
 
729
    public void setLockStrategy(LockStrategy lockStrategy) {
 
730
        this.lockStrategy = lockStrategy;
 
731
    }
 
732
    
 
733
    public void setLockStrategy(String lockStrategyName) {
 
734
        this.lockStrategyName = lockStrategyName;
 
735
    }
 
736
    
 
737
    public ArtifactDownloadReport download(
 
738
            Artifact artifact, 
 
739
            ArtifactResourceResolver resourceResolver, 
 
740
            ResourceDownloader resourceDownloader, 
 
741
            CacheDownloadOptions options) {
 
742
        final ArtifactDownloadReport adr = new ArtifactDownloadReport(artifact);
 
743
        boolean useOrigin = isUseOrigin();
 
744
        
 
745
        // TODO: see if we could lock on the artifact to download only, instead of the module
 
746
        // metadata artifact. We'd need to store artifact origin and is local in artifact specific
 
747
        // file to do so, or lock the metadata artifact only to update artifact origin, which would
 
748
        // mean acquiring nested locks, which can be a dangerous thing
 
749
        ModuleRevisionId mrid = artifact.getModuleRevisionId();
 
750
        if (!lockMetadataArtifact(mrid)) {
 
751
            adr.setDownloadStatus(DownloadStatus.FAILED);
 
752
            adr.setDownloadDetails("impossible to get lock for " + mrid);
 
753
            return adr;
 
754
        }
 
755
        try {
 
756
            DownloadListener listener = options.getListener();
 
757
            if (listener != null) {
 
758
                listener.needArtifact(this, artifact);
 
759
            }
 
760
            ArtifactOrigin origin = getSavedArtifactOrigin(artifact);
 
761
            // if we can use origin file, we just ask ivy for the file in cache, and it will
 
762
            // return the original one if possible. If we are not in useOrigin mode, we use the
 
763
            // getArchivePath method which always return a path in the actual cache
 
764
            File archiveFile = getArchiveFileInCache(artifact, origin, useOrigin);
 
765
 
 
766
            if (archiveFile.exists() && !options.isForce()) {
 
767
                adr.setDownloadStatus(DownloadStatus.NO);
 
768
                adr.setSize(archiveFile.length());
 
769
                adr.setArtifactOrigin(origin);
 
770
                adr.setLocalFile(archiveFile);
 
771
            } else {
 
772
                long start = System.currentTimeMillis();
 
773
                try {
 
774
                    ResolvedResource artifactRef = resourceResolver.resolve(artifact);
 
775
                    if (artifactRef != null) {
 
776
                        origin = new ArtifactOrigin(
 
777
                            artifact,
 
778
                            artifactRef.getResource().isLocal(),
 
779
                            artifactRef.getResource().getName());
 
780
                        if (useOrigin && artifactRef.getResource().isLocal()) {
 
781
                            saveArtifactOrigin(artifact, origin);
 
782
                            archiveFile = getArchiveFileInCache(artifact, origin);
 
783
                            adr.setDownloadStatus(DownloadStatus.NO);
 
784
                            adr.setSize(archiveFile.length());
 
785
                            adr.setArtifactOrigin(origin);
 
786
                            adr.setLocalFile(archiveFile);
 
787
                        } else {
 
788
                            // refresh archive file now that we better now its origin
 
789
                            archiveFile = getArchiveFileInCache(artifact, origin, useOrigin);
 
790
                            if (ResourceHelper.equals(artifactRef.getResource(), archiveFile)) {
 
791
                                throw new IllegalStateException("invalid settings for '"
 
792
                                    + resourceResolver
 
793
                                    + "': pointing repository to ivy cache is forbidden !");
 
794
                            } 
 
795
                            if (listener != null) {
 
796
                                listener.startArtifactDownload(this, artifactRef, artifact, origin);
 
797
                            }
 
798
 
 
799
                            resourceDownloader.download(
 
800
                                artifact, artifactRef.getResource(), archiveFile);
 
801
                            adr.setSize(archiveFile.length());
 
802
                            saveArtifactOrigin(artifact, origin);
 
803
                            adr.setDownloadTimeMillis(System.currentTimeMillis() - start);
 
804
                            adr.setDownloadStatus(DownloadStatus.SUCCESSFUL);
 
805
                            adr.setArtifactOrigin(origin);
 
806
                            adr.setLocalFile(archiveFile);
 
807
                        }
 
808
                    } else {
 
809
                        adr.setDownloadStatus(DownloadStatus.FAILED);
 
810
                        adr.setDownloadDetails(ArtifactDownloadReport.MISSING_ARTIFACT);
 
811
                        adr.setDownloadTimeMillis(System.currentTimeMillis() - start);
 
812
                    }
 
813
                } catch (Exception ex) {
 
814
                    adr.setDownloadStatus(DownloadStatus.FAILED);
 
815
                    adr.setDownloadDetails(ex.getMessage());
 
816
                    adr.setDownloadTimeMillis(System.currentTimeMillis() - start);
 
817
                }
 
818
            }
 
819
            if (listener != null) {
 
820
                listener.endArtifactDownload(this, artifact, adr, archiveFile);
 
821
            }
 
822
            return adr;
 
823
        } finally {
 
824
            unlockMetadataArtifact(mrid);
 
825
        }
 
826
    }
 
827
    
 
828
    public void originalToCachedModuleDescriptor(
 
829
            DependencyResolver resolver, ResolvedResource orginalMetadataRef,
 
830
            Artifact requestedMetadataArtifact,
 
831
            ResolvedModuleRevision rmr, ModuleDescriptorWriter writer) {
 
832
        ModuleDescriptor md = rmr.getDescriptor();
 
833
        Artifact originalMetadataArtifact = getOriginalMetadataArtifact(requestedMetadataArtifact);
 
834
        File mdFileInCache = getIvyFileInCache(md.getResolvedModuleRevisionId());
 
835
 
 
836
        ModuleRevisionId mrid = requestedMetadataArtifact.getModuleRevisionId();
 
837
        if (!lockMetadataArtifact(mrid)) {
 
838
            Message.warn("impossible to acquire lock for: " + mrid);
 
839
            return;
 
840
        }
 
841
        try {
 
842
            File originalFileInCache = getArchiveFileInCache(originalMetadataArtifact);
 
843
            writer.write(orginalMetadataRef, md, 
 
844
                originalFileInCache, 
 
845
                mdFileInCache);
 
846
 
 
847
            saveResolvers(md, resolver.getName(), resolver.getName());
 
848
            
 
849
            if (getSettings().getVersionMatcher().isDynamic(md.getModuleRevisionId())
 
850
                    && getTTL(md.getModuleRevisionId()) > 0) {
 
851
                saveResolvedRevision(md.getModuleRevisionId(), rmr.getId().getRevision());
 
852
            }
 
853
                
 
854
            if (!md.isDefault()) {
 
855
                rmr.getReport().setOriginalLocalFile(originalFileInCache);
 
856
            }
 
857
            rmr.getReport().setLocalFile(mdFileInCache);
 
858
        } catch (RuntimeException e) {
 
859
            throw e;
 
860
        } catch (Exception e) {
 
861
            Message.warn("impossible to put metadata file in cache: " 
 
862
                + (orginalMetadataRef == null 
 
863
                        ? String.valueOf(md.getResolvedModuleRevisionId()) 
 
864
                        : String.valueOf(orginalMetadataRef))
 
865
                + ". " + e.getClass().getName() + ": " + e.getMessage());
 
866
        } finally {
 
867
            unlockMetadataArtifact(mrid);
 
868
        }
 
869
    }
 
870
 
 
871
    public ResolvedModuleRevision cacheModuleDescriptor(
 
872
            DependencyResolver resolver, final ResolvedResource mdRef, DependencyDescriptor dd, 
 
873
            Artifact moduleArtifact, ResourceDownloader downloader, CacheMetadataOptions options) 
 
874
            throws ParseException {
 
875
        ModuleDescriptorParser parser = ModuleDescriptorParserRegistry
 
876
            .getInstance().getParser(mdRef.getResource());
 
877
        Date cachedPublicationDate = null;
 
878
        ArtifactDownloadReport report;
 
879
        ModuleRevisionId mrid = moduleArtifact.getModuleRevisionId();
 
880
        Artifact originalMetadataArtifact = getOriginalMetadataArtifact(moduleArtifact);
 
881
        if (!lockMetadataArtifact(mrid)) {
 
882
            Message.error("impossible to acquire lock for " + mrid);
 
883
            return null;
 
884
        }
 
885
        try {
 
886
            // now let's see if we can find it in cache and if it is up to date
 
887
            ResolvedModuleRevision rmr = doFindModuleInCache(mrid, options, null);
 
888
            if (rmr != null) {
 
889
                if (rmr.getDescriptor().isDefault() && rmr.getResolver() != resolver) {
 
890
                    Message.verbose("\t" + getName() + ": found revision in cache: " + mrid
 
891
                        + " (resolved by " + rmr.getResolver().getName()
 
892
                        + "): but it's a default one, maybe we can find a better one");
 
893
                } else {
 
894
                    if (!isCheckmodified(dd, mrid, options) && !isChanging(dd, mrid, options)) {
 
895
                        Message.verbose("\t" + getName() + ": revision in cache: " + mrid);
 
896
                        rmr.getReport().setSearched(true);
 
897
                        return rmr;
 
898
                    }
 
899
                    long repLastModified = mdRef.getLastModified();
 
900
                    long cacheLastModified = rmr.getDescriptor().getLastModified();
 
901
                    if (!rmr.getDescriptor().isDefault() && repLastModified <= cacheLastModified) {
 
902
                        Message.verbose("\t" + getName() + ": revision in cache (not updated): "
 
903
                            + mrid);
 
904
                        rmr.getReport().setSearched(true);
 
905
                        return rmr;
 
906
                    } else {
 
907
                        Message.verbose("\t" + getName() + ": revision in cache is not up to date: "
 
908
                            + mrid);
 
909
                        if (isChanging(dd, mrid, options)) {
 
910
                            // ivy file has been updated, we should see if it has a new publication
 
911
                            // date to see if a new download is required (in case the dependency is
 
912
                            // a changing one)
 
913
                            cachedPublicationDate = 
 
914
                                rmr.getDescriptor().getResolvedPublicationDate();
 
915
                        }
 
916
                    }
 
917
                }
 
918
            }
 
919
 
 
920
            // now download module descriptor and parse it
 
921
            report = download(
 
922
                originalMetadataArtifact, 
 
923
                new ArtifactResourceResolver() {
 
924
                    public ResolvedResource resolve(Artifact artifact) {
 
925
                        return mdRef;
 
926
                    }
 
927
                }, downloader, 
 
928
                new CacheDownloadOptions().setListener(options.getListener()).setForce(true));
 
929
            Message.verbose("\t" + report); 
 
930
 
 
931
            if (report.getDownloadStatus() == DownloadStatus.FAILED) {
 
932
                Message.warn("problem while downloading module descriptor: " + mdRef.getResource() 
 
933
                    + ": " + report.getDownloadDetails() 
 
934
                    + " (" + report.getDownloadTimeMillis() + "ms)");
 
935
                return null;
 
936
            }
 
937
 
 
938
            try {
 
939
                ModuleDescriptor md = getStaledMd(parser, options, report.getLocalFile()); 
 
940
                if (md == null) {
 
941
                    throw new IllegalStateException(
 
942
                        "module descriptor parser returned a null module descriptor, " 
 
943
                        + "which is not allowed. "
 
944
                        + "parser=" + parser 
 
945
                        + "; parser class=" + parser.getClass().getName()
 
946
                        + "; module descriptor resource=" + mdRef.getResource());
 
947
                }
 
948
                Message.debug("\t" + getName() + ": parsed downloaded md file for " + mrid 
 
949
                    + "; parsed=" + md.getModuleRevisionId());
 
950
 
 
951
                // check if we should delete old artifacts
 
952
                boolean deleteOldArtifacts = false;
 
953
                if (cachedPublicationDate != null
 
954
                        && !cachedPublicationDate.equals(md.getResolvedPublicationDate())) {
 
955
                    // artifacts have changed, they should be downloaded again
 
956
                    Message.verbose(mrid + " has changed: deleting old artifacts");
 
957
                    deleteOldArtifacts = true;
 
958
                }
 
959
                if (deleteOldArtifacts) {
 
960
                    String[] confs = md.getConfigurationsNames();
 
961
                    for (int i = 0; i < confs.length; i++) {
 
962
                        Artifact[] arts = md.getArtifacts(confs[i]);
 
963
                        for (int j = 0; j < arts.length; j++) {
 
964
                            Artifact transformedArtifact = NameSpaceHelper.transform(
 
965
                                arts[j], options.getNamespace().getToSystemTransformer());
 
966
                            ArtifactOrigin origin = getSavedArtifactOrigin(
 
967
                                transformedArtifact);
 
968
                            File artFile = getArchiveFileInCache(
 
969
                                transformedArtifact, origin, false);
 
970
                            if (artFile.exists()) {
 
971
                                Message.debug("deleting " + artFile);
 
972
                                artFile.delete();
 
973
                            }
 
974
                            removeSavedArtifactOrigin(transformedArtifact);
 
975
                        }
 
976
                    }
 
977
                } else if (isChanging(dd, mrid, options)) {
 
978
                    Message.verbose(mrid
 
979
                        + " is changing, but has not changed: will trust cached artifacts if any");
 
980
                }
 
981
                
 
982
                MetadataArtifactDownloadReport madr 
 
983
                    = new MetadataArtifactDownloadReport(md.getMetadataArtifact());
 
984
                madr.setSearched(true);
 
985
                madr.setDownloadStatus(report.getDownloadStatus());
 
986
                madr.setDownloadDetails(report.getDownloadDetails());
 
987
                madr.setArtifactOrigin(report.getArtifactOrigin());
 
988
                madr.setDownloadTimeMillis(report.getDownloadTimeMillis());
 
989
                madr.setOriginalLocalFile(report.getLocalFile());
 
990
                madr.setSize(report.getSize());
 
991
                saveArtifactOrigin(md.getMetadataArtifact(), report.getArtifactOrigin());
 
992
                
 
993
                return new ResolvedModuleRevision(resolver, resolver, md, madr);
 
994
            } catch (IOException ex) {
 
995
                Message.warn("io problem while parsing ivy file: " + mdRef.getResource() + ": "
 
996
                    + ex.getMessage());
 
997
                return null;
 
998
            }
 
999
        } finally {
 
1000
            unlockMetadataArtifact(mrid);
 
1001
        }
 
1002
        
 
1003
    }
 
1004
 
 
1005
    // lock used to lock all metadata related information access
 
1006
    private boolean lockMetadataArtifact(ModuleRevisionId mrid) {
 
1007
        Artifact artifact = getDefaultMetadataArtifact(mrid);
 
1008
        try {
 
1009
            // we need to provide an artifact origin to be sure we do not end up in a stack overflow
 
1010
            // if the cache pattern is using original name, and the substitution thus trying to get
 
1011
            // the saved artifact origin value which in turns calls this method
 
1012
            return getLockStrategy().lockArtifact(artifact, 
 
1013
                getArchiveFileInCache(artifact, getDefaultMetadataArtifactOrigin(mrid)));
 
1014
        } catch (InterruptedException e) {
 
1015
            Thread.currentThread().interrupt(); // reset interrupt status 
 
1016
            throw new RuntimeException("operation interrupted");
 
1017
        }
 
1018
    }
 
1019
 
 
1020
    private void unlockMetadataArtifact(ModuleRevisionId mrid) {
 
1021
        Artifact artifact = getDefaultMetadataArtifact(mrid);
 
1022
        getLockStrategy().unlockArtifact(artifact, 
 
1023
            getArchiveFileInCache(artifact, getDefaultMetadataArtifactOrigin(mrid)));
 
1024
    }
 
1025
    
 
1026
    
 
1027
    private ArtifactOrigin getDefaultMetadataArtifactOrigin(ModuleRevisionId mrid) {
 
1028
        // it's important to say the origin is not local to make sure it won't ever be used for
 
1029
        // anything else than original token
 
1030
        return new ArtifactOrigin(
 
1031
            DefaultArtifact.newIvyArtifact(mrid, null), false, getIvyFileInCache(mrid).getPath());
 
1032
    }
 
1033
    
 
1034
    private Artifact getDefaultMetadataArtifact(ModuleRevisionId mrid) {
 
1035
        return new DefaultArtifact(mrid, new Date(), "metadata", "metadata", "ivy", true);
 
1036
    }
 
1037
 
 
1038
    // not used any more, but maybe useful for finer grain locking when downloading artifacts
 
1039
//    private boolean lockArtifact(Artifact artifact) {
 
1040
//        try {
 
1041
//            return getLockStrategy().lockArtifact(artifact, 
 
1042
//                getArchiveFileInCache(artifact, null));
 
1043
//        } catch (InterruptedException e) {
 
1044
//            Thread.currentThread().interrupt(); // reset interrupt status 
 
1045
//            throw new RuntimeException("operation interrupted");
 
1046
//        }
 
1047
//    }
 
1048
//    
 
1049
//    private void unlockArtifact(Artifact artifact) {
 
1050
//        getLockStrategy().unlockArtifact(artifact, getArchiveFileInCache(artifact, null));
 
1051
//    }
 
1052
    
 
1053
    public Artifact getOriginalMetadataArtifact(Artifact moduleArtifact) {
 
1054
        return DefaultArtifact.cloneWithAnotherType(
 
1055
            moduleArtifact, moduleArtifact.getType() + ".original");
 
1056
    }
 
1057
    
 
1058
 
 
1059
    private boolean isOriginalMetadataArtifact(Artifact artifact) {
 
1060
        return artifact.isMetadata() 
 
1061
            && artifact.getType().endsWith(".original");
 
1062
    }
 
1063
 
 
1064
    private boolean isChanging(
 
1065
            DependencyDescriptor dd, ModuleRevisionId requestedRevisionId, 
 
1066
            CacheMetadataOptions options) {
 
1067
        return dd.isChanging() 
 
1068
            || getChangingMatcher(options).matches(requestedRevisionId.getRevision());
 
1069
    }
 
1070
 
 
1071
    private Matcher getChangingMatcher(CacheMetadataOptions options) {
 
1072
        String changingPattern = options.getChangingPattern() != null 
 
1073
                ? options.getChangingPattern() : this.changingPattern;
 
1074
        if (changingPattern == null) {
 
1075
            return NoMatcher.INSTANCE;
 
1076
        }
 
1077
        String changingMatcherName = options.getChangingMatcherName() != null 
 
1078
            ? options.getChangingMatcherName() : this.changingMatcherName;
 
1079
        PatternMatcher matcher = settings.getMatcher(changingMatcherName);
 
1080
        if (matcher == null) {
 
1081
            throw new IllegalStateException("unknown matcher '" + changingMatcherName
 
1082
                    + "'. It is set as changing matcher in " + this);
 
1083
        }
 
1084
        return matcher.getMatcher(changingPattern);
 
1085
    }
 
1086
 
 
1087
    private boolean isCheckmodified(
 
1088
            DependencyDescriptor dd, ModuleRevisionId requestedRevisionId, 
 
1089
            CacheMetadataOptions options) {
 
1090
        if (options.isCheckmodified() != null) {
 
1091
            return options.isCheckmodified().booleanValue();
 
1092
        }
 
1093
        return isCheckmodified();
 
1094
    }
 
1095
    
 
1096
    public void clean() {
 
1097
        FileUtil.forceDelete(getBasedir());
 
1098
    }
 
1099
 
 
1100
    public void dumpSettings() {
 
1101
        Message.verbose("\t" + getName());
 
1102
        Message.debug("\t\tivyPattern: " + getIvyPattern());
 
1103
        Message.debug("\t\tartifactPattern: " + getArtifactPattern());
 
1104
        Message.debug("\t\tlockingStrategy: " + getLockStrategy().getName());
 
1105
        Message.debug("\t\tchangingPattern: " + getChangingPattern());
 
1106
        Message.debug("\t\tchangingMatcher: " + getChangingMatcherName());
 
1107
    }
 
1108
 
 
1109
}