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

« back to all changes in this revision

Viewing changes to src/java/org/apache/ivy/plugins/resolver/AbstractPatternsBasedResolver.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.plugins.resolver;
 
19
 
 
20
import java.util.ArrayList;
 
21
import java.util.Arrays;
 
22
import java.util.Collection;
 
23
import java.util.Collections;
 
24
import java.util.Date;
 
25
import java.util.HashMap;
 
26
import java.util.HashSet;
 
27
import java.util.Iterator;
 
28
import java.util.LinkedHashSet;
 
29
import java.util.List;
 
30
import java.util.ListIterator;
 
31
import java.util.Map;
 
32
import java.util.Set;
 
33
import java.util.Map.Entry;
 
34
 
 
35
import org.apache.ivy.core.IvyContext;
 
36
import org.apache.ivy.core.IvyPatternHelper;
 
37
import org.apache.ivy.core.module.descriptor.Artifact;
 
38
import org.apache.ivy.core.module.descriptor.DefaultArtifact;
 
39
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
 
40
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
 
41
import org.apache.ivy.core.module.id.ModuleRevisionId;
 
42
import org.apache.ivy.core.resolve.IvyNode;
 
43
import org.apache.ivy.core.resolve.ResolveData;
 
44
import org.apache.ivy.core.settings.IvyPattern;
 
45
import org.apache.ivy.plugins.conflict.ConflictManager;
 
46
import org.apache.ivy.plugins.matcher.Matcher;
 
47
import org.apache.ivy.plugins.resolver.util.MDResolvedResource;
 
48
import org.apache.ivy.plugins.resolver.util.ResolvedResource;
 
49
import org.apache.ivy.plugins.resolver.util.ResourceMDParser;
 
50
import org.apache.ivy.plugins.version.VersionMatcher;
 
51
import org.apache.ivy.util.Message;
 
52
 
 
53
/**
 
54
 *
 
55
 */
 
56
public abstract class AbstractPatternsBasedResolver extends BasicResolver {
 
57
 
 
58
    private static final Map IVY_ARTIFACT_ATTRIBUTES = new HashMap();
 
59
    static {
 
60
        IVY_ARTIFACT_ATTRIBUTES.put(IvyPatternHelper.ARTIFACT_KEY, "ivy");
 
61
        IVY_ARTIFACT_ATTRIBUTES.put(IvyPatternHelper.TYPE_KEY, "ivy");
 
62
        IVY_ARTIFACT_ATTRIBUTES.put(IvyPatternHelper.EXT_KEY, "xml");
 
63
    }
 
64
 
 
65
    private List ivyPatterns = new ArrayList(); // List (String pattern)
 
66
 
 
67
    private List artifactPatterns = new ArrayList(); // List (String pattern)
 
68
 
 
69
    private boolean m2compatible = false;
 
70
 
 
71
    public AbstractPatternsBasedResolver() {
 
72
    }
 
73
 
 
74
    public ResolvedResource findIvyFileRef(DependencyDescriptor dd, ResolveData data) {
 
75
        ModuleRevisionId mrid = dd.getDependencyRevisionId();
 
76
        if (isM2compatible()) {
 
77
            mrid = convertM2IdForResourceSearch(mrid);
 
78
        }
 
79
        return findResourceUsingPatterns(mrid, ivyPatterns, DefaultArtifact.newIvyArtifact(mrid,
 
80
            data.getDate()), getRMDParser(dd, data), data.getDate());
 
81
    }
 
82
 
 
83
    protected ResolvedResource findArtifactRef(Artifact artifact, Date date) {
 
84
        ModuleRevisionId mrid = artifact.getModuleRevisionId();
 
85
        if (isM2compatible()) {
 
86
            mrid = convertM2IdForResourceSearch(mrid);
 
87
        }
 
88
        return findResourceUsingPatterns(mrid, artifactPatterns, artifact,
 
89
            getDefaultRMDParser(artifact.getModuleRevisionId().getModuleId()), date);
 
90
    }
 
91
 
 
92
    protected ResolvedResource findResourceUsingPatterns(ModuleRevisionId moduleRevision,
 
93
            List patternList, Artifact artifact, ResourceMDParser rmdparser, Date date) {
 
94
        List resolvedResources = new ArrayList();
 
95
        Set foundRevisions = new HashSet();
 
96
        boolean dynamic = getSettings().getVersionMatcher().isDynamic(moduleRevision);
 
97
        boolean stop = false;
 
98
        for (Iterator iter = patternList.iterator(); iter.hasNext() && !stop;) {
 
99
            String pattern = (String) iter.next();
 
100
            ResolvedResource rres = findResourceUsingPattern(
 
101
                moduleRevision, pattern, artifact, rmdparser, date);
 
102
            if ((rres != null) && !foundRevisions.contains(rres.getRevision())) {
 
103
                // only add the first found ResolvedResource for each revision
 
104
                foundRevisions.add(rres.getRevision());
 
105
                resolvedResources.add(rres);
 
106
                stop = !dynamic; // stop iterating if we are not searching a dynamic revision
 
107
            }
 
108
        }
 
109
 
 
110
        if (resolvedResources.size() > 1) {
 
111
            ResolvedResource[] rress = (ResolvedResource[]) resolvedResources
 
112
                    .toArray(new ResolvedResource[resolvedResources.size()]);
 
113
            return findResource(rress, rmdparser, moduleRevision, date);
 
114
        } else if (resolvedResources.size() == 1) {
 
115
            return (ResolvedResource) resolvedResources.get(0);
 
116
        } else {
 
117
            return null;
 
118
        }
 
119
    }
 
120
 
 
121
    protected abstract ResolvedResource findResourceUsingPattern(ModuleRevisionId mrid,
 
122
            String pattern, Artifact artifact, ResourceMDParser rmdparser, Date date);
 
123
 
 
124
    public ResolvedResource findResource(ResolvedResource[] rress, ResourceMDParser rmdparser,
 
125
            ModuleRevisionId mrid, Date date) {
 
126
        String name = getName();
 
127
        VersionMatcher versionMatcher = getSettings().getVersionMatcher();
 
128
        
 
129
        ResolvedResource found = null;
 
130
        List sorted = getLatestStrategy().sort(rress);
 
131
        List rejected = new ArrayList();
 
132
        List foundBlacklisted = new ArrayList();
 
133
        IvyContext context = IvyContext.getContext();
 
134
        
 
135
        for (ListIterator iter = sorted.listIterator(sorted.size()); iter.hasPrevious();) {
 
136
            ResolvedResource rres = (ResolvedResource) iter.previous();
 
137
            if (filterNames(new ArrayList(Collections.singleton(rres.getRevision()))).isEmpty()) {
 
138
                Message.debug("\t" + name + ": filtered by name: " + rres);
 
139
                continue;
 
140
            }
 
141
            if ((date != null && rres.getLastModified() > date.getTime())) {
 
142
                Message.verbose("\t" + name + ": too young: " + rres);
 
143
                rejected.add(rres.getRevision() + " (" + rres.getLastModified() + ")");
 
144
                continue;
 
145
            }
 
146
            ModuleRevisionId foundMrid = ModuleRevisionId.newInstance(mrid, rres.getRevision());
 
147
            
 
148
            ResolveData data = context.getResolveData();
 
149
            if (data != null
 
150
                    && data.getReport() != null 
 
151
                    && data.isBlacklisted(data.getReport().getConfiguration(), foundMrid)) {
 
152
                Message.debug("\t" + name + ": blacklisted: " + rres);
 
153
                rejected.add(rres.getRevision() + " (blacklisted)");
 
154
                foundBlacklisted.add(foundMrid);
 
155
                continue;
 
156
            }
 
157
            
 
158
            if (!versionMatcher.accept(mrid, foundMrid)) {
 
159
                Message.debug("\t" + name + ": rejected by version matcher: " + rres);
 
160
                rejected.add(rres.getRevision());
 
161
                continue;
 
162
            }
 
163
            if (versionMatcher.needModuleDescriptor(mrid, foundMrid)) {
 
164
                ResolvedResource r = rmdparser.parse(rres.getResource(), rres.getRevision());
 
165
                if (r == null) {
 
166
                    Message.debug("\t" + name 
 
167
                        + ": impossible to get module descriptor resource: " + rres);
 
168
                    rejected.add(rres.getRevision() + " (no or bad MD)");
 
169
                    continue;
 
170
                }
 
171
                ModuleDescriptor md = ((MDResolvedResource) r).getResolvedModuleRevision()
 
172
                        .getDescriptor();
 
173
                if (md.isDefault()) {
 
174
                    Message.debug("\t" + name + ": default md rejected by version matcher" 
 
175
                            + "requiring module descriptor: " + rres);
 
176
                    rejected.add(rres.getRevision() + " (MD)");
 
177
                    continue;
 
178
                } else if (!versionMatcher.accept(mrid, md)) {
 
179
                    Message.debug("\t" + name + ": md rejected by version matcher: " + rres);
 
180
                    rejected.add(rres.getRevision() + " (MD)");
 
181
                    continue;
 
182
                } else {
 
183
                    found = r;
 
184
                }
 
185
            } else {
 
186
                found = rres;
 
187
            }
 
188
 
 
189
            if (found != null) {
 
190
                if (!found.getResource().exists()) {
 
191
                    Message.debug("\t" + name + ": resource not reachable for " + mrid + ": res="
 
192
                            + found.getResource());
 
193
                    logAttempt(found.getResource().toString());
 
194
                    continue;
 
195
                }
 
196
                break;
 
197
            }
 
198
        }
 
199
        if (found == null && !rejected.isEmpty()) {
 
200
            logAttempt(rejected.toString());
 
201
        }
 
202
        if (found == null && !foundBlacklisted.isEmpty()) {
 
203
            // all acceptable versions have been blacklisted, this means that an unsolvable conflict
 
204
            // has been found
 
205
            DependencyDescriptor dd = context.getDependencyDescriptor();
 
206
            IvyNode parentNode = context.getResolveData().getNode(dd.getParentRevisionId());
 
207
            ConflictManager cm = parentNode.getConflictManager(mrid.getModuleId());
 
208
            cm.handleAllBlacklistedRevisions(dd, foundBlacklisted);
 
209
        }
 
210
 
 
211
        return found;
 
212
    }
 
213
 
 
214
    protected Collection findNames(Map tokenValues, String token) {
 
215
        Collection names = new HashSet();
 
216
        names.addAll(findIvyNames(tokenValues, token));
 
217
        if (isAllownomd()) {
 
218
            names.addAll(findArtifactNames(tokenValues, token));
 
219
        }
 
220
        return names;
 
221
    }
 
222
 
 
223
    protected Collection findIvyNames(Map tokenValues, String token) {
 
224
        Collection names = new HashSet();
 
225
        tokenValues = new HashMap(tokenValues);
 
226
        tokenValues.put(IvyPatternHelper.ARTIFACT_KEY, "ivy");
 
227
        tokenValues.put(IvyPatternHelper.TYPE_KEY, "ivy");
 
228
        tokenValues.put(IvyPatternHelper.EXT_KEY, "xml");
 
229
        if (isM2compatible()) {
 
230
            convertM2TokenValuesForResourceSearch(tokenValues);
 
231
        }
 
232
        findTokenValues(names, getIvyPatterns(), tokenValues, token);
 
233
        filterNames(names);
 
234
        return names;
 
235
    }
 
236
 
 
237
    protected Collection findArtifactNames(Map tokenValues, String token) {
 
238
        Collection names = new HashSet();
 
239
        tokenValues = new HashMap(tokenValues);
 
240
        tokenValues
 
241
                .put(IvyPatternHelper.ARTIFACT_KEY, tokenValues.get(IvyPatternHelper.MODULE_KEY));
 
242
        tokenValues.put(IvyPatternHelper.TYPE_KEY, "jar");
 
243
        tokenValues.put(IvyPatternHelper.EXT_KEY, "jar");
 
244
        if (isM2compatible()) {
 
245
            convertM2TokenValuesForResourceSearch(tokenValues);
 
246
        }
 
247
        findTokenValues(names, getArtifactPatterns(), tokenValues, token);
 
248
        filterNames(names);
 
249
        return names;
 
250
    }
 
251
 
 
252
    public Map[] listTokenValues(String[] tokens, Map criteria) {
 
253
        Set result = new LinkedHashSet();
 
254
        
 
255
        // use ivy patterns
 
256
        List ivyPatterns = getIvyPatterns();
 
257
        Map tokenValues = new HashMap(criteria);
 
258
        tokenValues.put(IvyPatternHelper.TYPE_KEY, "ivy");
 
259
        tokenValues.put(IvyPatternHelper.EXT_KEY, "xml");
 
260
        if (isM2compatible()) {
 
261
            convertM2TokenValuesForResourceSearch(tokenValues);
 
262
        }
 
263
        for (Iterator it = ivyPatterns.iterator(); it.hasNext();) {
 
264
            String ivyPattern = (String) it.next();
 
265
            result.addAll(resolveTokenValues(tokens, ivyPattern, tokenValues, false));
 
266
        }
 
267
        
 
268
        if (isAllownomd()) {
 
269
            List artifactPatterns = getArtifactPatterns();
 
270
            tokenValues = new HashMap(criteria);
 
271
            tokenValues.put(IvyPatternHelper.TYPE_KEY, "jar");
 
272
            tokenValues.put(IvyPatternHelper.EXT_KEY, "jar");
 
273
            if (isM2compatible()) {
 
274
                convertM2TokenValuesForResourceSearch(tokenValues);
 
275
            }
 
276
            for (Iterator it = artifactPatterns.iterator(); it.hasNext();) {
 
277
                String artifactPattern = (String) it.next();
 
278
                result.addAll(resolveTokenValues(tokens, artifactPattern, tokenValues, true));
 
279
            }
 
280
        }
 
281
        
 
282
        return (Map[]) result.toArray(new Map[result.size()]);
 
283
    }
 
284
    
 
285
    private Set resolveTokenValues(String[] tokens, String pattern, Map criteria, boolean noMd) {
 
286
        Set result = new LinkedHashSet();
 
287
        Set tokenSet = new HashSet(Arrays.asList(tokens));
 
288
        
 
289
        Map tokenValues = new HashMap();
 
290
        for (Iterator it = criteria.entrySet().iterator(); it.hasNext();) {
 
291
            Map.Entry entry = (Entry) it.next();
 
292
            Object key = entry.getKey();
 
293
            Object value = entry.getValue();
 
294
            if (value instanceof String) {
 
295
                tokenValues.put(key, value);
 
296
            }
 
297
        }
 
298
        
 
299
        if (tokenSet.isEmpty()) {
 
300
            // no more tokens to resolve
 
301
            result.add(tokenValues);
 
302
            return result;
 
303
        }
 
304
        
 
305
        String partiallyResolvedPattern = IvyPatternHelper.substituteTokens(pattern, tokenValues);
 
306
        String token = IvyPatternHelper.getFirstToken(partiallyResolvedPattern);
 
307
        if ((token == null) && exist(partiallyResolvedPattern)) {
 
308
            // no more tokens to resolve
 
309
            result.add(tokenValues);
 
310
            return result;
 
311
        }
 
312
        
 
313
        tokenSet.remove(token);
 
314
 
 
315
        Matcher matcher = null;
 
316
        Object criteriaForToken = criteria.get(token);
 
317
        if (criteriaForToken instanceof Matcher) {
 
318
            matcher = (Matcher) criteriaForToken;
 
319
        }
 
320
 
 
321
        String[] values = listTokenValues(partiallyResolvedPattern, token);
 
322
        if (values == null) {
 
323
            return result;
 
324
        }
 
325
 
 
326
        List vals = new ArrayList(Arrays.asList(values));
 
327
        filterNames(vals);
 
328
        
 
329
        for (Iterator it = vals.iterator(); it.hasNext();) {
 
330
            String value = (String) it.next();
 
331
            if ((matcher != null) && !matcher.matches(value)) {
 
332
                continue;
 
333
            }
 
334
            
 
335
            tokenValues.put(token, value);
 
336
            String moreResolvedPattern = IvyPatternHelper.substituteTokens(
 
337
                partiallyResolvedPattern, tokenValues);
 
338
 
 
339
            Map newCriteria = new HashMap(criteria);
 
340
            newCriteria.put(token, value);
 
341
            if (noMd && "artifact".equals(token)) {
 
342
                newCriteria.put("module", value);
 
343
            } else if (noMd && "module".equals(token)) {
 
344
                newCriteria.put("artifact", value);
 
345
            }
 
346
            result.addAll(resolveTokenValues(
 
347
                (String[]) tokenSet.toArray(new String[tokenSet.size()]), 
 
348
                moreResolvedPattern, newCriteria, noMd));
 
349
        }
 
350
 
 
351
        return result;
 
352
    }
 
353
    
 
354
    protected abstract String[] listTokenValues(String pattern, String token);
 
355
    
 
356
    protected abstract boolean exist(String path);
 
357
 
 
358
    /**
 
359
     * Filters names before returning them in the findXXXNames or findTokenValues method.
 
360
     * <p>
 
361
     * Remember to call the super implementation when overriding this method.
 
362
     * </p>
 
363
     * 
 
364
     * @param names
 
365
     *            the list to filter.
 
366
     * @return the filtered list
 
367
     */
 
368
    protected Collection filterNames(Collection names) {
 
369
        getSettings().filterIgnore(names);
 
370
        return names;
 
371
    }
 
372
 
 
373
    protected void findTokenValues(Collection names, List patterns, Map tokenValues, String token) {
 
374
        //to be overridden by subclasses wanting to have listing features
 
375
    }
 
376
 
 
377
    /**
 
378
     * example of pattern : ~/Workspace/[module]/[module].ivy.xml
 
379
     * 
 
380
     * @param pattern
 
381
     */
 
382
    public void addIvyPattern(String pattern) {
 
383
        ivyPatterns.add(pattern);
 
384
    }
 
385
 
 
386
    public void addArtifactPattern(String pattern) {
 
387
        artifactPatterns.add(pattern);
 
388
    }
 
389
 
 
390
    public List getIvyPatterns() {
 
391
        return Collections.unmodifiableList(ivyPatterns);
 
392
    }
 
393
 
 
394
    public List getArtifactPatterns() {
 
395
        return Collections.unmodifiableList(artifactPatterns);
 
396
    }
 
397
 
 
398
    protected void setIvyPatterns(List patterns) {
 
399
        ivyPatterns = patterns;
 
400
    }
 
401
 
 
402
    protected void setArtifactPatterns(List patterns) {
 
403
        artifactPatterns = patterns;
 
404
    }
 
405
 
 
406
    /*
 
407
     * Methods respecting ivy conf method specifications
 
408
     */
 
409
    public void addConfiguredIvy(IvyPattern p) {
 
410
        ivyPatterns.add(p.getPattern());
 
411
    }
 
412
 
 
413
    public void addConfiguredArtifact(IvyPattern p) {
 
414
        artifactPatterns.add(p.getPattern());
 
415
    }
 
416
 
 
417
    public void dumpSettings() {
 
418
        super.dumpSettings();
 
419
        Message.debug("\t\tm2compatible: " + isM2compatible());
 
420
        Message.debug("\t\tivy patterns:");
 
421
        for (ListIterator iter = getIvyPatterns().listIterator(); iter.hasNext();) {
 
422
            String p = (String) iter.next();
 
423
            Message.debug("\t\t\t" + p);
 
424
        }
 
425
        Message.debug("\t\tartifact patterns:");
 
426
        for (ListIterator iter = getArtifactPatterns().listIterator(); iter.hasNext();) {
 
427
            String p = (String) iter.next();
 
428
            Message.debug("\t\t\t" + p);
 
429
        }
 
430
    }
 
431
 
 
432
    public boolean isM2compatible() {
 
433
        return m2compatible;
 
434
    }
 
435
 
 
436
    public void setM2compatible(boolean compatible) {
 
437
        m2compatible = compatible;
 
438
    }
 
439
 
 
440
    protected ModuleRevisionId convertM2IdForResourceSearch(ModuleRevisionId mrid) {
 
441
        if (mrid.getOrganisation() == null || mrid.getOrganisation().indexOf('.') == -1) {
 
442
            return mrid;
 
443
        }
 
444
        return ModuleRevisionId.newInstance(mrid.getOrganisation().replace('.', '/'), 
 
445
            mrid.getName(), mrid.getBranch(), mrid.getRevision(), 
 
446
            mrid.getQualifiedExtraAttributes());
 
447
    }
 
448
 
 
449
    protected String convertM2OrganizationForResourceSearch(String org) {
 
450
        return org.replace('.', '/');
 
451
    }
 
452
 
 
453
    protected void convertM2TokenValuesForResourceSearch(Map tokenValues) {
 
454
        if (tokenValues.get(IvyPatternHelper.ORGANISATION_KEY) instanceof String) {
 
455
            tokenValues.put(IvyPatternHelper.ORGANISATION_KEY, 
 
456
                convertM2OrganizationForResourceSearch(
 
457
                    (String) tokenValues.get(IvyPatternHelper.ORGANISATION_KEY)));
 
458
        }
 
459
    }
 
460
 
 
461
}