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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
18
package org.apache.ivy.plugins.parser.xml;
21
import java.io.IOException;
22
import java.io.InputStream;
23
import java.net.MalformedURLException;
25
import java.text.ParseException;
26
import java.util.Arrays;
27
import java.util.List;
30
import javax.xml.parsers.ParserConfigurationException;
32
import org.apache.ivy.Ivy;
33
import org.apache.ivy.core.IvyContext;
34
import org.apache.ivy.core.module.descriptor.Configuration;
35
import org.apache.ivy.core.module.descriptor.ConfigurationAware;
36
import org.apache.ivy.core.module.descriptor.DefaultArtifact;
37
import org.apache.ivy.core.module.descriptor.DefaultDependencyArtifactDescriptor;
38
import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
39
import org.apache.ivy.core.module.descriptor.DefaultExcludeRule;
40
import org.apache.ivy.core.module.descriptor.DefaultIncludeRule;
41
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
42
import org.apache.ivy.core.module.descriptor.DependencyArtifactDescriptor;
43
import org.apache.ivy.core.module.descriptor.ExcludeRule;
44
import org.apache.ivy.core.module.descriptor.IncludeRule;
45
import org.apache.ivy.core.module.descriptor.License;
46
import org.apache.ivy.core.module.descriptor.MDArtifact;
47
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
48
import org.apache.ivy.core.module.descriptor.OverrideDependencyDescriptorMediator;
49
import org.apache.ivy.core.module.id.ArtifactId;
50
import org.apache.ivy.core.module.id.ModuleId;
51
import org.apache.ivy.core.module.id.ModuleRevisionId;
52
import org.apache.ivy.plugins.conflict.ConflictManager;
53
import org.apache.ivy.plugins.conflict.FixedConflictManager;
54
import org.apache.ivy.plugins.matcher.PatternMatcher;
55
import org.apache.ivy.plugins.namespace.Namespace;
56
import org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser;
57
import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
58
import org.apache.ivy.plugins.parser.ParserSettings;
59
import org.apache.ivy.plugins.repository.Resource;
60
import org.apache.ivy.plugins.repository.url.URLResource;
61
import org.apache.ivy.util.Message;
62
import org.apache.ivy.util.XMLHelper;
63
import org.apache.ivy.util.extendable.ExtendableItemHelper;
64
import org.xml.sax.Attributes;
65
import org.xml.sax.SAXException;
68
* Parses an xml ivy file and output a ModuleDescriptor. For dependency and performance reasons, it
69
* uses only the SAX API, which makes the parsing code harder to understand.
71
public class XmlModuleDescriptorParser extends AbstractModuleDescriptorParser {
72
static final String[] DEPENDENCY_REGULAR_ATTRIBUTES = new String[] {"org", "name", "branch",
73
"branchConstraint", "rev", "revConstraint", "force", "transitive", "changing", "conf"};
75
private static final XmlModuleDescriptorParser INSTANCE = new XmlModuleDescriptorParser();
77
public static XmlModuleDescriptorParser getInstance() {
81
protected XmlModuleDescriptorParser() {
87
* the url pointing to the file to parse
89
* the real resource to parse, used for log only
92
* @throws ParseException
95
public ModuleDescriptor parseDescriptor(ParserSettings ivySettings, URL xmlURL, Resource res,
96
boolean validate) throws ParseException, IOException {
97
Parser parser = newParser(ivySettings);
98
parser.setValidate(validate);
99
parser.setResource(res);
100
parser.setInput(xmlURL);
102
return parser.getModuleDescriptor();
105
/** Used for test purpose */
106
ModuleDescriptor parseDescriptor(ParserSettings ivySettings, InputStream descriptor,
107
Resource res, boolean validate) throws ParseException, IOException {
108
Parser parser = newParser(ivySettings);
109
parser.setValidate(validate);
110
parser.setResource(res);
111
parser.setInput(descriptor);
113
return parser.getModuleDescriptor();
117
* Instantiates a Parser instance responsible for actual parsing of Ivy files.
119
* Override this method if you want to use a custom Parser.
123
* the settings to use during parsing
124
* @return the Parser instance used for parsing Ivy files
126
protected Parser newParser(ParserSettings ivySettings) {
127
return new Parser(this, ivySettings);
130
public boolean accept(Resource res) {
131
return true; // this the default parser, it thus accepts all resources
134
public void toIvyFile(InputStream is, Resource res, File destFile, ModuleDescriptor md)
135
throws IOException, ParseException {
138
if (md instanceof DefaultModuleDescriptor) {
139
DefaultModuleDescriptor dmd = (DefaultModuleDescriptor) md;
140
ns = dmd.getNamespace();
142
XmlModuleDescriptorUpdater.update(is, res, destFile,
144
.setSettings(IvyContext.getContext().getSettings())
145
.setStatus(md.getStatus())
146
.setRevision(md.getResolvedModuleRevisionId().getRevision())
147
.setPubdate(md.getResolvedPublicationDate())
148
.setUpdateBranch(false)
150
} catch (SAXException e) {
151
ParseException ex = new ParseException("exception occured while parsing " + res, 0);
161
public static class Parser extends AbstractParser {
162
public static final class State {
163
public static final int NONE = 0;
165
public static final int INFO = 1;
167
public static final int CONF = 2;
169
public static final int PUB = 3;
171
public static final int DEP = 4;
173
public static final int DEP_ARTIFACT = 5;
175
public static final int ARTIFACT_INCLUDE = 6;
177
public static final int ARTIFACT_EXCLUDE = 7;
179
public static final int CONFLICT = 8;
181
public static final int EXCLUDE = 9;
183
public static final int DEPS = 10;
185
public static final int DESCRIPTION = 11;
187
public static final int EXTRA_INFO = 12;
193
protected static final List ALLOWED_VERSIONS = Arrays.asList(
194
new String[] {"1.0", "1.1", "1.2", "1.3", "1.4", "2.0"});
196
/* how and what do we have to parse */
197
private ParserSettings settings;
198
private boolean validate = true;
199
private URL descriptorURL;
200
private InputStream descriptorInput;
204
private int state = State.NONE;
205
private PatternMatcher defaultMatcher;
206
private DefaultDependencyDescriptor dd;
207
private ConfigurationAware confAware;
208
private MDArtifact artifact;
210
private boolean artifactsDeclared = false;
211
private StringBuffer buffer;
212
private String descriptorVersion;
213
private String[] publicationsDefaultConf;
215
public Parser(ModuleDescriptorParser parser, ParserSettings ivySettings) {
217
settings = ivySettings;
220
public void setInput(InputStream descriptorInput) {
221
this.descriptorInput = descriptorInput;
224
public void setInput(URL descriptorURL) {
225
this.descriptorURL = descriptorURL;
228
public void setValidate(boolean validate) {
229
this.validate = validate;
232
public void parse() throws ParseException,
235
URL schemaURL = validate ? getSchemaURL() : null;
236
if (descriptorURL != null) {
237
XMLHelper.parse(descriptorURL, schemaURL, this);
239
XMLHelper.parse(descriptorInput, schemaURL, this, null);
241
checkConfigurations();
242
replaceConfigurationWildcards();
243
getMd().setModuleArtifact(
244
DefaultArtifact.newIvyArtifact(
245
getMd().getResolvedModuleRevisionId(), getMd().getPublicationDate()));
246
if (!artifactsDeclared) {
247
String[] confs = getMd().getConfigurationsNames();
248
for (int i = 0; i < confs.length; i++) {
249
getMd().addArtifact(confs[i],
250
new MDArtifact(getMd(), getMd().getModuleRevisionId().getName(),
255
} catch (ParserConfigurationException ex) {
256
IllegalStateException ise = new IllegalStateException(ex.getMessage() + " in "
260
} catch (Exception ex) {
262
ParseException pe = new ParseException(ex.getMessage() + " in " + descriptorURL, 0);
268
public void startElement(String uri, String localName, String qName, Attributes attributes)
269
throws SAXException {
271
if (state == State.DESCRIPTION) {
272
//make sure we don't interpret any tag while in description tag
273
buffer.append("<" + qName + ">");
275
} else if ("ivy-module".equals(qName)) {
276
ivyModuleStarted(attributes);
277
} else if ("info".equals(qName)) {
278
infoStarted(attributes);
279
} else if (state == State.INFO && "license".equals(qName)) {
280
getMd().addLicense(new License(settings.substitute(attributes.getValue("name")),
281
settings.substitute(attributes.getValue("url"))));
282
} else if (state == State.INFO && "description".equals(qName)) {
283
getMd().setHomePage(settings.substitute(attributes.getValue("homepage")));
284
state = State.DESCRIPTION;
285
buffer = new StringBuffer();
286
} else if (state == State.INFO && "ivyauthor".equals(qName)) {
287
// nothing to do, we don't store this
288
} else if (state == State.INFO && "repository".equals(qName)) {
289
// nothing to do, we don't store this
290
} else if (state == State.INFO && isOtherNamespace(qName)) {
291
buffer = new StringBuffer();
292
state = State.EXTRA_INFO;
293
} else if ("configurations".equals(qName)) {
294
configurationStarted(attributes);
295
} else if ("publications".equals(qName)) {
296
publicationsStarted(attributes);
297
} else if ("dependencies".equals(qName)) {
298
dependenciesStarted(attributes);
299
} else if ("conflicts".equals(qName)) {
300
if (!descriptorVersion.startsWith("1.")) {
301
Message.deprecated("using conflicts section is deprecated: "
302
+ "please use hints section instead. Ivy file URL: " + descriptorURL);
304
state = State.CONFLICT;
305
checkConfigurations();
306
} else if ("artifact".equals(qName)) {
307
artifactStarted(qName, attributes);
308
} else if ("include".equals(qName) && state == State.DEP) {
309
addIncludeRule(qName, attributes);
310
} else if ("exclude".equals(qName) && state == State.DEP) {
311
addExcludeRule(qName, attributes);
312
} else if ("exclude".equals(qName) && state == State.DEPS) {
313
state = State.EXCLUDE;
314
parseRule(qName, attributes);
315
getMd().addExcludeRule((ExcludeRule) confAware);
316
} else if ("dependency".equals(qName)) {
317
dependencyStarted(attributes);
318
} else if ("conf".equals(qName)) {
319
confStarted(attributes);
320
} else if ("mapped".equals(qName)) {
321
dd.addDependencyConfiguration(conf, settings.substitute(attributes
323
} else if (("conflict".equals(qName) && state == State.DEPS)
324
|| "manager".equals(qName) && state == State.CONFLICT) {
325
managerStarted(attributes, state == State.CONFLICT ? "name" : "manager");
326
} else if ("override".equals(qName) && state == State.DEPS) {
327
mediationOverrideStarted(attributes);
328
} else if ("include".equals(qName) && state == State.CONF) {
329
includeConfStarted(attributes);
330
} else if (validate && state != State.EXTRA_INFO && state != State.DESCRIPTION) {
331
addError("unknown tag " + qName);
333
} catch (Exception ex) {
334
if (ex instanceof SAXException) {
335
throw (SAXException) ex;
337
SAXException sax = new SAXException("Problem occured while parsing ivy file: "
338
+ ex.getMessage(), ex);
344
protected void publicationsStarted(Attributes attributes) {
346
artifactsDeclared = true;
347
checkConfigurations();
348
String defaultConf = settings.substitute(attributes.getValue("defaultconf"));
349
if (defaultConf != null) {
350
setPublicationsDefaultConf(defaultConf);
354
protected void setPublicationsDefaultConf(String defaultConf) {
355
this.publicationsDefaultConf = defaultConf == null ? null : defaultConf.split(",");
358
protected boolean isOtherNamespace(String qName) {
359
return qName.indexOf(':') != -1;
362
protected void managerStarted(Attributes attributes, String managerAtt) {
363
String org = settings.substitute(attributes.getValue("org"));
364
org = org == null ? PatternMatcher.ANY_EXPRESSION : org;
365
String mod = settings.substitute(attributes.getValue("module"));
366
mod = mod == null ? PatternMatcher.ANY_EXPRESSION : mod;
368
String name = settings.substitute(attributes.getValue(managerAtt));
369
String rev = settings.substitute(attributes.getValue("rev"));
371
String[] revs = rev.split(",");
372
for (int i = 0; i < revs.length; i++) {
373
revs[i] = revs[i].trim();
375
cm = new FixedConflictManager(revs);
376
} else if (name != null) {
377
cm = settings.getConflictManager(name);
379
addError("unknown conflict manager: " + name);
383
addError("bad conflict manager: no manager nor rev");
386
String matcherName = settings.substitute(attributes.getValue("matcher"));
387
PatternMatcher matcher = matcherName == null ? defaultMatcher : settings
388
.getMatcher(matcherName);
389
if (matcher == null) {
390
addError("unknown matcher: " + matcherName);
393
getMd().addConflictManager(new ModuleId(org, mod), matcher, cm);
396
protected void mediationOverrideStarted(Attributes attributes) {
397
String org = settings.substitute(attributes.getValue("org"));
398
org = org == null ? PatternMatcher.ANY_EXPRESSION : org;
399
String mod = settings.substitute(attributes.getValue("module"));
400
mod = mod == null ? PatternMatcher.ANY_EXPRESSION : mod;
401
String rev = settings.substitute(attributes.getValue("rev"));
402
String branch = settings.substitute(attributes.getValue("branch"));
403
String matcherName = settings.substitute(attributes.getValue("matcher"));
404
PatternMatcher matcher = matcherName == null ? defaultMatcher : settings
405
.getMatcher(matcherName);
406
if (matcher == null) {
407
addError("unknown matcher: " + matcherName);
410
getMd().addDependencyDescriptorMediator(
411
new ModuleId(org, mod), matcher,
412
new OverrideDependencyDescriptorMediator(branch, rev));
415
protected void includeConfStarted(Attributes attributes)
416
throws SAXException, IOException, ParserConfigurationException, ParseException {
417
URL url = settings.getRelativeUrlResolver().getURL(descriptorURL,
418
settings.substitute(attributes.getValue("file")),
419
settings.substitute(attributes.getValue("url")));
422
throw new SAXException("include tag must have a file or an url attribute");
425
// create a new temporary parser to read the configurations from
426
// the specified file.
427
Parser parser = new Parser(getModuleDescriptorParser(), settings);
428
parser.setInput(url);
429
parser.setMd(new DefaultModuleDescriptor(getModuleDescriptorParser(),
430
new URLResource(url)));
431
XMLHelper.parse(url , null, parser);
433
// add the configurations from this temporary parser to this module descriptor
434
Configuration[] configs = parser.getModuleDescriptor().getConfigurations();
435
for (int i = 0; i < configs.length; i++) {
436
getMd().addConfiguration(configs[i]);
438
if (parser.getDefaultConfMapping() != null) {
439
Message.debug("setting default conf from imported configurations file: "
440
+ parser.getDefaultConfMapping());
441
setDefaultConfMapping(parser.getDefaultConfMapping());
443
if (parser.getMd().isMappingOverride()) {
444
Message.debug("enabling mapping-override from imported configurations"
446
getMd().setMappingOverride(true);
450
protected void confStarted(Attributes attributes) {
451
String conf = settings.substitute(attributes.getValue("name"));
454
String visibility = settings.substitute(attributes.getValue("visibility"));
455
String ext = settings.substitute(attributes.getValue("extends"));
456
String transitiveValue = attributes.getValue("transitive");
457
boolean transitive = (transitiveValue == null) ? true : Boolean
458
.valueOf(attributes.getValue("transitive")).booleanValue();
459
String deprecated = attributes.getValue("deprecated");
460
Configuration configuration = new Configuration(conf,
461
Configuration.Visibility
462
.getVisibility(visibility == null ? "public"
463
: visibility), settings.substitute(attributes
464
.getValue("description")), ext == null ? null : ext
465
.split(","), transitive, deprecated);
466
ExtendableItemHelper.fillExtraAttributes(settings, configuration, attributes,
467
new String[] {"name", "visibility", "extends", "transitive",
468
"description", "deprecated"});
469
getMd().addConfiguration(configuration);
472
if ("*".equals(conf)) {
473
String[] confs = getMd().getConfigurationsNames();
474
for (int i = 0; i < confs.length; i++) {
475
artifact.addConfiguration(confs[i]);
476
getMd().addArtifact(confs[i], artifact);
479
artifact.addConfiguration(conf);
480
getMd().addArtifact(conf, artifact);
485
String mappeds = settings.substitute(attributes.getValue("mapped"));
486
if (mappeds != null) {
487
String[] mapped = mappeds.split(",");
488
for (int i = 0; i < mapped.length; i++) {
489
dd.addDependencyConfiguration(conf, mapped[i].trim());
493
case State.DEP_ARTIFACT:
494
case State.ARTIFACT_INCLUDE:
495
case State.ARTIFACT_EXCLUDE:
496
addConfiguration(conf);
500
addError("conf tag found in invalid tag: " + state);
506
protected void dependencyStarted(Attributes attributes) {
508
String org = settings.substitute(attributes.getValue("org"));
510
org = getMd().getModuleRevisionId().getOrganisation();
512
boolean force = Boolean.valueOf(settings.substitute(attributes.getValue("force")))
514
boolean changing = Boolean.valueOf(
515
settings.substitute(attributes.getValue("changing"))).booleanValue();
517
String transitiveValue = settings.substitute(attributes.getValue("transitive"));
518
boolean transitive = (transitiveValue == null) ? true : Boolean.valueOf(
519
attributes.getValue("transitive")).booleanValue();
521
String name = settings.substitute(attributes.getValue("name"));
522
String branch = settings.substitute(attributes.getValue("branch"));
523
String branchConstraint = settings.substitute(attributes.getValue("branchConstraint"));
524
String rev = settings.substitute(attributes.getValue("rev"));
525
String revConstraint = settings.substitute(attributes.getValue("revConstraint"));
526
revConstraint = revConstraint == null ? rev : revConstraint;
527
Map extraAttributes = ExtendableItemHelper.getExtraAttributes(
528
settings, attributes, DEPENDENCY_REGULAR_ATTRIBUTES);
529
dd = new DefaultDependencyDescriptor(
531
ModuleRevisionId.newInstance(org, name, branch, rev, extraAttributes),
532
ModuleRevisionId.newInstance(
533
org, name, branchConstraint, revConstraint, extraAttributes),
534
force, changing, transitive);
535
getMd().addDependency(dd);
536
String confs = settings.substitute(attributes.getValue("conf"));
537
if (confs != null && confs.length() > 0) {
538
parseDepsConfs(confs, dd);
542
protected void artifactStarted(String qName, Attributes attributes)
543
throws MalformedURLException {
544
if (state == State.PUB) {
545
// this is a published artifact
546
String artName = settings.substitute(attributes.getValue("name"));
547
artName = artName == null ? getMd().getModuleRevisionId().getName() : artName;
548
String type = settings.substitute(attributes.getValue("type"));
549
type = type == null ? "jar" : type;
550
String ext = settings.substitute(attributes.getValue("ext"));
551
ext = ext != null ? ext : type;
552
String url = settings.substitute(attributes.getValue("url"));
553
artifact = new MDArtifact(getMd(), artName, type, ext, url == null ? null
554
: new URL(url), ExtendableItemHelper.getExtraAttributes(
555
settings, attributes, new String[] {"ext", "type", "name", "conf"}));
556
String confs = settings.substitute(attributes.getValue("conf"));
557
// only add confs if they are specified. if they aren't, endElement will
559
// only if there are no conf defined in sub elements
560
if (confs != null && confs.length() > 0) {
562
if ("*".equals(confs)) {
563
conf = getMd().getConfigurationsNames();
565
conf = confs.split(",");
567
for (int i = 0; i < conf.length; i++) {
568
artifact.addConfiguration(conf[i].trim());
569
getMd().addArtifact(conf[i].trim(), artifact);
572
} else if (state == State.DEP) {
573
// this is an artifact asked for a particular dependency
574
addDependencyArtifacts(qName, attributes);
575
} else if (validate) {
576
addError("artifact tag found in invalid tag: " + state);
580
protected void dependenciesStarted(Attributes attributes) {
582
String defaultConf = settings.substitute(attributes.getValue("defaultconf"));
583
if (defaultConf != null) {
584
setDefaultConf(defaultConf);
586
defaultConf = settings.substitute(attributes.getValue("defaultconfmapping"));
587
if (defaultConf != null) {
588
setDefaultConfMapping(defaultConf);
590
String confMappingOverride = settings.substitute(attributes
591
.getValue("confmappingoverride"));
592
if (confMappingOverride != null) {
593
getMd().setMappingOverride(Boolean.valueOf(confMappingOverride).booleanValue());
595
checkConfigurations();
598
protected void configurationStarted(Attributes attributes) {
600
setDefaultConfMapping(settings
601
.substitute(attributes.getValue("defaultconfmapping")));
603
.setMappingOverride(Boolean.valueOf(
604
settings.substitute(attributes.getValue("confmappingoverride")))
608
protected void infoStarted(Attributes attributes) {
610
String org = settings.substitute(attributes.getValue("organisation"));
611
String module = settings.substitute(attributes.getValue("module"));
612
String revision = settings.substitute(attributes.getValue("revision"));
613
String branch = settings.substitute(attributes.getValue("branch"));
614
getMd().setModuleRevisionId(ModuleRevisionId.newInstance(org, module, branch,
615
revision, ExtendableItemHelper.getExtraAttributes(settings, attributes,
617
"organisation", "module", "revision", "status", "publication",
618
"branch", "namespace", "default", "resolver"})));
620
String namespace = settings.substitute(attributes.getValue("namespace"));
621
if (namespace != null) {
622
Namespace ns = settings.getNamespace(namespace);
624
Message.warn("namespace not found for " + getMd().getModuleRevisionId()
627
getMd().setNamespace(ns);
631
String status = settings.substitute(attributes.getValue("status"));
632
getMd().setStatus(status == null ? settings.getStatusManager().getDefaultStatus()
634
getMd().setDefault(Boolean.valueOf(settings.substitute(attributes.getValue("default")))
636
String pubDate = settings.substitute(attributes.getValue("publication"));
637
if (pubDate != null && pubDate.length() > 0) {
639
getMd().setPublicationDate(Ivy.DATE_FORMAT.parse(pubDate));
640
} catch (ParseException e) {
641
addError("invalid publication date format: " + pubDate);
642
getMd().setPublicationDate(getDefaultPubDate());
645
getMd().setPublicationDate(getDefaultPubDate());
649
protected void ivyModuleStarted(Attributes attributes) throws SAXException {
650
descriptorVersion = attributes.getValue("version");
651
int versionIndex = ALLOWED_VERSIONS.indexOf(descriptorVersion);
652
if (versionIndex == -1) {
653
addError("invalid version " + descriptorVersion);
654
throw new SAXException("invalid version " + descriptorVersion);
656
if (versionIndex >= ALLOWED_VERSIONS.indexOf("1.3")) {
657
Message.debug("post 1.3 ivy file: using " + PatternMatcher.EXACT
658
+ " as default matcher");
659
defaultMatcher = settings.getMatcher(PatternMatcher.EXACT);
661
Message.debug("pre 1.3 ivy file: using " + PatternMatcher.EXACT_OR_REGEXP
662
+ " as default matcher");
663
defaultMatcher = settings.getMatcher(PatternMatcher.EXACT_OR_REGEXP);
666
for (int i = 0; i < attributes.getLength(); i++) {
667
if (attributes.getQName(i).startsWith("xmlns:")) {
668
getMd().addExtraAttributeNamespace(
669
attributes.getQName(i).substring("xmlns:".length()),
670
attributes.getValue(i));
675
protected void addDependencyArtifacts(String tag, Attributes attributes)
676
throws MalformedURLException {
677
state = State.DEP_ARTIFACT;
678
parseRule(tag, attributes);
681
protected void addIncludeRule(String tag, Attributes attributes)
682
throws MalformedURLException {
683
state = State.ARTIFACT_INCLUDE;
684
parseRule(tag, attributes);
687
protected void addExcludeRule(String tag, Attributes attributes)
688
throws MalformedURLException {
689
state = State.ARTIFACT_EXCLUDE;
690
parseRule(tag, attributes);
693
protected void parseRule(String tag, Attributes attributes) throws MalformedURLException {
694
String name = settings.substitute(attributes.getValue("name"));
696
name = settings.substitute(attributes.getValue("artifact"));
698
name = "artifact".equals(tag) ? dd.getDependencyId().getName()
699
: PatternMatcher.ANY_EXPRESSION;
702
String type = settings.substitute(attributes.getValue("type"));
704
type = "artifact".equals(tag) ? "jar" : PatternMatcher.ANY_EXPRESSION;
706
String ext = settings.substitute(attributes.getValue("ext"));
707
ext = ext != null ? ext : type;
708
if (state == State.DEP_ARTIFACT) {
709
String url = settings.substitute(attributes.getValue("url"));
710
Map extraAtt = ExtendableItemHelper.getExtraAttributes(settings, attributes,
711
new String[] {"name", "type", "ext", "url", "conf"});
712
confAware = new DefaultDependencyArtifactDescriptor(dd, name, type, ext,
713
url == null ? null : new URL(url), extraAtt);
714
} else if (state == State.ARTIFACT_INCLUDE) {
715
PatternMatcher matcher = getPatternMatcher(attributes.getValue("matcher"));
716
String org = settings.substitute(attributes.getValue("org"));
717
org = org == null ? PatternMatcher.ANY_EXPRESSION : org;
718
String module = settings.substitute(attributes.getValue("module"));
719
module = module == null ? PatternMatcher.ANY_EXPRESSION : module;
720
ArtifactId aid = new ArtifactId(new ModuleId(org, module), name, type, ext);
721
Map extraAtt = ExtendableItemHelper.getExtraAttributes(settings, attributes,
722
new String[] {"org", "module", "name", "type", "ext", "matcher", "conf"});
723
confAware = new DefaultIncludeRule(aid, matcher, extraAtt);
724
} else { // _state == ARTIFACT_EXCLUDE || EXCLUDE
725
PatternMatcher matcher = getPatternMatcher(attributes.getValue("matcher"));
726
String org = settings.substitute(attributes.getValue("org"));
727
org = org == null ? PatternMatcher.ANY_EXPRESSION : org;
728
String module = settings.substitute(attributes.getValue("module"));
729
module = module == null ? PatternMatcher.ANY_EXPRESSION : module;
730
ArtifactId aid = new ArtifactId(new ModuleId(org, module), name, type, ext);
731
Map extraAtt = ExtendableItemHelper.getExtraAttributes(settings, attributes,
732
new String[] {"org", "module", "name", "type", "ext", "matcher", "conf"});
733
confAware = new DefaultExcludeRule(aid, matcher, extraAtt);
735
String confs = settings.substitute(attributes.getValue("conf"));
736
// only add confs if they are specified. if they aren't, endElement will handle this
737
// only if there are no conf defined in sub elements
738
if (confs != null && confs.length() > 0) {
740
if ("*".equals(confs)) {
741
conf = getMd().getConfigurationsNames();
743
conf = confs.split(",");
745
for (int i = 0; i < conf.length; i++) {
746
addConfiguration(conf[i].trim());
751
protected void addConfiguration(String c) {
752
confAware.addConfiguration(c);
753
if (state == State.EXCLUDE) {
754
// we are adding a configuration to a module wide exclude rule
755
// we have nothing special to do here, the rule has already been added to the module
758
// we are currently adding a configuration to either an include, exclude or artifact
760
// of a dependency. This means that we have to add this element to the corresponding
762
// of the current dependency descriptor
763
if (confAware instanceof DependencyArtifactDescriptor) {
764
dd.addDependencyArtifact(c, (DependencyArtifactDescriptor) confAware);
765
} else if (confAware instanceof IncludeRule) {
766
dd.addIncludeRule(c, (IncludeRule) confAware);
767
} else if (confAware instanceof ExcludeRule) {
768
dd.addExcludeRule(c, (ExcludeRule) confAware);
773
protected PatternMatcher getPatternMatcher(String m) {
774
String matcherName = settings.substitute(m);
775
PatternMatcher matcher = matcherName == null ? defaultMatcher : settings
776
.getMatcher(matcherName);
777
if (matcher == null) {
778
throw new IllegalArgumentException("unknown matcher " + matcherName);
784
public void characters(char[] ch, int start, int length) throws SAXException {
785
if (buffer != null) {
786
buffer.append(ch, start, length);
791
public void endElement(String uri, String localName, String qName) throws SAXException {
792
if (state == State.PUB && "artifact".equals(qName)
793
&& artifact.getConfigurations().length == 0) {
794
String[] confs = publicationsDefaultConf == null
795
? getMd().getConfigurationsNames()
796
: publicationsDefaultConf;
797
for (int i = 0; i < confs.length; i++) {
798
artifact.addConfiguration(confs[i].trim());
799
getMd().addArtifact(confs[i].trim(), artifact);
801
} else if ("configurations".equals(qName)) {
802
checkConfigurations();
803
} else if ((state == State.DEP_ARTIFACT && "artifact".equals(qName))
804
|| (state == State.ARTIFACT_INCLUDE && "include".equals(qName))
805
|| (state == State.ARTIFACT_EXCLUDE && "exclude".equals(qName))) {
807
if (confAware.getConfigurations().length == 0) {
808
String[] confs = getMd().getConfigurationsNames();
809
for (int i = 0; i < confs.length; i++) {
810
addConfiguration(confs[i]);
814
} else if ("exclude".equals(qName) && state == State.EXCLUDE) {
815
if (confAware.getConfigurations().length == 0) {
816
String[] confs = getMd().getConfigurationsNames();
817
for (int i = 0; i < confs.length; i++) {
818
addConfiguration(confs[i]);
823
} else if ("dependency".equals(qName) && state == State.DEP) {
824
if (dd.getModuleConfigurations().length == 0) {
825
parseDepsConfs(getDefaultConf(), dd);
828
} else if ("dependencies".equals(qName) && state == State.DEPS) {
830
} else if (state == State.INFO && "info".equals(qName)) {
832
} else if (state == State.DESCRIPTION && "description".equals(qName)) {
833
getMd().setDescription(buffer == null ? "" : buffer.toString().trim());
836
} else if (state == State.EXTRA_INFO) {
837
getMd().addExtraInfo(qName, buffer == null ? "" : buffer.toString());
840
} else if (state == State.DESCRIPTION) {
841
if (buffer.toString().endsWith("<" + qName + ">")) {
842
buffer.deleteCharAt(buffer.length() - 1);
845
buffer.append("</" + qName + ">");
850
protected void checkConfigurations() {
851
if (getMd().getConfigurations().length == 0) {
852
getMd().addConfiguration(new Configuration("default"));
856
protected void replaceConfigurationWildcards() {
857
Configuration[] configs = getMd().getConfigurations();
858
for (int i = 0; i < configs.length; i++) {
859
configs[i].replaceWildcards(getMd());
863
/* getters and setters available for extension only */
864
protected ParserSettings getSettings() {
868
protected URL getDescriptorURL() {
869
return descriptorURL;
872
protected InputStream getDescriptorInput() {
873
return descriptorInput;
876
protected int getState() {
880
protected void setState(int state) {
884
protected PatternMatcher getDefaultMatcher() {
885
return defaultMatcher;
888
protected DefaultDependencyDescriptor getDd() {
892
protected void setDd(DefaultDependencyDescriptor dd) {
896
protected ConfigurationAware getConfAware() {
900
protected void setConfAware(ConfigurationAware confAware) {
901
this.confAware = confAware;
904
protected MDArtifact getArtifact() {
908
protected void setArtifact(MDArtifact artifact) {
909
this.artifact = artifact;
912
protected String getConf() {
916
protected void setConf(String conf) {
920
protected boolean isArtifactsDeclared() {
921
return artifactsDeclared;
924
protected void setArtifactsDeclared(boolean artifactsDeclared) {
925
this.artifactsDeclared = artifactsDeclared;
928
protected StringBuffer getBuffer() {
932
protected void setBuffer(StringBuffer buffer) {
933
this.buffer = buffer;
936
protected String getDescriptorVersion() {
937
return descriptorVersion;
940
protected void setDescriptorVersion(String descriptorVersion) {
941
this.descriptorVersion = descriptorVersion;
944
protected String[] getPublicationsDefaultConf() {
945
return publicationsDefaultConf;
948
protected void setPublicationsDefaultConf(String[] publicationsDefaultConf) {
949
this.publicationsDefaultConf = publicationsDefaultConf;
952
protected boolean isValidate() {
956
protected URL getSchemaURL() {
957
return getClass().getResource("ivy.xsd");
961
public String toString() {