1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.maven.resolver.internal.ant.types;
20
21 import java.io.File;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24
25 import org.apache.maven.model.Model;
26 import org.apache.maven.resolver.internal.ant.AntRepoSys;
27 import org.apache.maven.resolver.internal.ant.ProjectWorkspaceReader;
28 import org.apache.maven.resolver.internal.ant.tasks.RefTask;
29 import org.apache.tools.ant.BuildException;
30 import org.apache.tools.ant.PropertyHelper;
31 import org.apache.tools.ant.Task;
32 import org.apache.tools.ant.types.Reference;
33
34 /**
35 * Represents a Maven POM file as an Ant {@code DataType}.
36 * <p>
37 * This type allows an existing {@code pom.xml} file to be loaded into the Ant build environment.
38 * The POM's metadata (such as groupId, artifactId, version, etc.) can be accessed directly or reused
39 * in other Maven Resolver tasks like {@link org.apache.maven.resolver.internal.ant.tasks.Deploy Deploy},
40 * {@link org.apache.maven.resolver.internal.ant.tasks.Install Install}
41 * </p>
42 *
43 * <h2>Usage Example:</h2>
44 * <pre>{@code
45 * <pom file="target/generated-pom.xml" id="my.pom"/>
46 *
47 * <echo message="Group ID is ${pom.groupId}"/>
48 * <echo message="Version is ${pom.version}"/>
49 *
50 * <deploy>
51 * <pom refid="my.pom"/>
52 * <repository id="release" url="https://repo.mycompany.com/releases"/>
53 * </deploy>
54 * }</pre>
55 *
56 * <h2>Attributes:</h2>
57 * <ul>
58 * <li><strong>file</strong> — the path to the {@code pom.xml} file to load</li>
59 * </ul>
60 *
61 * <h2>Exposed Ant Properties:</h2>
62 * When a POM is loaded, the following properties become available for use in your build script:
63 * <ul>
64 * <li>{@code ${pom.groupId}}</li>
65 * <li>{@code ${pom.artifactId}}</li>
66 * <li>{@code ${pom.version}}</li>
67 * <li>{@code ${pom.packaging}}</li>
68 * <li>{@code ${pom.name}}</li>
69 * <li>{@code ${pom.description}} (if present)</li>
70 * </ul>
71 *
72 * These properties enable consistent reuse of project metadata across Ant targets and tasks.
73 * <p>
74 * If you want a different property prefix, you can set it when you register the POM, e.g.:
75 * </p>
76 * <pre>{@code
77 * <pom file="target/generated-pom.xml" id="my.pom" prefix="lib"/>
78 * }</pre>
79 *
80 * <h2>Typical Use Cases:</h2>
81 * <ul>
82 * <li>Reusing existing Maven coordinates in Ant-based deployments</li>
83 * <li>Injecting POM metadata into artifact creation or reporting tasks</li>
84 * <li>Keeping build logic in sync with Maven configuration</li>
85 * </ul>
86 *
87 * @see org.apache.maven.resolver.internal.ant.tasks.Deploy
88 * @see org.apache.maven.resolver.internal.ant.tasks.Install
89 * @see org.apache.maven.resolver.internal.ant.tasks.CreatePom
90 */
91 public class Pom extends RefTask {
92
93 private Model model;
94
95 private String id;
96
97 private File file;
98
99 private String groupId;
100
101 private String artifactId;
102
103 private String version;
104
105 private String packaging = "jar";
106
107 private RemoteRepositories remoteRepositories;
108
109 private String coords;
110
111 /**
112 * Creates an empty {@code Pom} instance.
113 * <p>
114 * Attributes such as {@code groupId}, {@code artifactId}, and {@code version} can be set individually,
115 * or the POM can be initialized from a {@code file} or via a reference ({@code refid}).
116 * </p>
117 *
118 * <p>
119 * Ant uses this constructor when instantiating the datatype from a build script.
120 * </p>
121 *
122 * @see #setGroupId(String)
123 * @see #setArtifactId(String)
124 * @see #setVersion(String)
125 * @see #setFile(java.io.File)
126 * @see #setRefid(org.apache.tools.ant.types.Reference)
127 */
128 public Pom() {
129 // Default constructor for Ant task
130 }
131
132 /**
133 * Resolves this object if defined as a reference and verifies that it is a
134 * {@code Pom} instance.
135 *
136 * @return the referenced {@code Pom} instance
137 * @throws org.apache.tools.ant.BuildException if the reference is invalid
138 *
139 * @see #isReference()
140 * @see #getCheckedRef()
141 */
142 protected Pom getRef() {
143 return (Pom) getCheckedRef();
144 }
145
146 /**
147 * Validates that this POM definition is complete and usable.
148 * <p>
149 * If this object is a reference, validation is delegated to the referenced {@code Pom}.
150 * Otherwise, the method checks that either a {@link #setFile(File) POM file} is provided,
151 * or all of the required Maven coordinates — {@code groupId}, {@code artifactId}, and {@code version} —
152 * are explicitly set.
153 * </p>
154 *
155 * @throws org.apache.tools.ant.BuildException if required attributes are missing
156 * and no POM file is specified
157 *
158 * @see #isReference()
159 * @see #setFile(File)
160 * @see #setGroupId(String)
161 * @see #setArtifactId(String)
162 * @see #setVersion(String)
163 */
164 public void validate() {
165 if (isReference()) {
166 getRef().validate();
167 } else {
168 if (file == null) {
169 if (groupId == null) {
170 throw new BuildException("You must specify the 'groupId' for the POM");
171 }
172 if (artifactId == null) {
173 throw new BuildException("You must specify the 'artifactId' for the POM");
174 }
175 if (version == null) {
176 throw new BuildException("You must specify the 'version' for the POM");
177 }
178 }
179 }
180 }
181
182 @Override
183 public void setRefid(Reference ref) {
184 if (id != null || file != null || groupId != null || artifactId != null || version != null) {
185 throw tooManyAttributes();
186 }
187 if (remoteRepositories != null) {
188 throw noChildrenAllowed();
189 }
190 super.setRefid(ref);
191 }
192
193 /**
194 * Sets the internal identifier for this POM.
195 * <p>
196 * This {@code id} is not the same as Ant's built-in {@code id} attribute, but may be used
197 * internally by the task logic (e.g., for naming, logging, or referencing the POM).
198 * </p>
199 *
200 * <p>
201 * This method must not be used if this object is defined as a reference ({@code refid}),
202 * or if attributes are otherwise disallowed in the current context.
203 * </p>
204 *
205 * @param id the internal identifier to assign
206 *
207 * @throws org.apache.tools.ant.BuildException if attribute usage is disallowed
208 *
209 * @see #isReference()
210 */
211 public void setId(String id) {
212 checkAttributesAllowed();
213 this.id = id;
214 }
215
216 /**
217 * Returns the file that was set via {@link #setFile(File)} to load the POM from.
218 * <p>
219 * If a file was specified, it is used as the source for reading the POM’s metadata
220 * instead of defining coordinates manually. This is useful when you want to reference
221 * an existing {@code pom.xml} file directly.
222 * </p>
223 *
224 * <p>
225 * If this {@code Pom} is defined as a reference ({@code refid}),
226 * the file is retrieved from the referenced {@code Pom} instance.
227 * </p>
228 *
229 * @return the POM file, or {@code null} if not set
230 *
231 * @see #setFile(File)
232 * @see #isReference()
233 */
234 public File getFile() {
235 if (isReference()) {
236 return getRef().getFile();
237 }
238 return file;
239 }
240
241 /**
242 * Sets the file from which to load the POM.
243 * <p>
244 * This is an alternative to specifying Maven coordinates manually. When set,
245 * the POM's metadata is loaded directly from the given file.
246 * </p>
247 *
248 * <p>This method must not be used in combination with:</p>
249 * <ul>
250 * <li>{@link #setGroupId(String)}, {@link #setArtifactId(String)}, {@link #setVersion(String)}, or {@link #setCoords(String)}</li>
251 * <li>or if this object is defined as a {@code refid}</li>
252 * </ul>
253 * <p>
254 * Doing so will raise a {@link org.apache.tools.ant.BuildException}.
255 * </p>
256 *
257 * @param file the file containing the POM
258 *
259 * @throws org.apache.tools.ant.BuildException if attributes are in conflict or not allowed
260 *
261 * @see #getFile()
262 * @see #setCoords(String)
263 * @see #isReference()
264 */
265 public void setFile(File file) {
266 checkAttributesAllowed();
267 if (groupId != null || artifactId != null || version != null) {
268 throw ambiguousSource();
269 }
270
271 this.file = file;
272 }
273
274 /**
275 * Returns the {@code groupId} of the POM.
276 * <p>
277 * The group ID uniquely identifies the organization or project to which the artifact belongs,
278 * such as {@code org.apache.maven}. This value is typically required when manually specifying
279 * Maven coordinates using {@link #setGroupId(String)} or {@link #setCoords(String)}.
280 * </p>
281 *
282 * <p>
283 * If this {@code Pom} is defined as a reference ({@code refid}),
284 * the value is delegated to the referenced {@code Pom} instance.
285 * </p>
286 *
287 * @return the group ID, or {@code null} if not set
288 *
289 * @see #setGroupId(String)
290 * @see #isReference()
291 */
292 public String getGroupId() {
293 if (isReference()) {
294 return getRef().getGroupId();
295 }
296 return groupId;
297 }
298
299 /**
300 * Sets the {@code groupId} for the POM.
301 * <p>
302 * The group ID typically represents the project's organization or domain,
303 * such as {@code org.apache.maven} or {@code com.example}.
304 * This value is required when specifying coordinates manually.
305 * </p>
306 *
307 * <p>This method must not be called if:</p>
308 * <ul>
309 * <li>{@code groupId} has already been set (directly or via {@link #setCoords(String)}),</li>
310 * <li>or if a POM file has been specified via {@link #setFile(java.io.File)},</li>
311 * <li>or if this object is defined via a {@code refid}.</li>
312 * </ul>
313 * <p>
314 * Violations will result in a {@link org.apache.tools.ant.BuildException}.
315 * </p>
316 *
317 * @param groupId the Maven group ID
318 *
319 * @throws org.apache.tools.ant.BuildException if attributes are in conflict or not allowed
320 *
321 * @see #getGroupId()
322 * @see #setArtifactId(String)
323 * @see #setVersion(String)
324 * @see #setCoords(String)
325 * @see #setFile(java.io.File)
326 * @see #isReference()
327 */
328 public void setGroupId(String groupId) {
329 checkAttributesAllowed();
330 if (this.groupId != null) {
331 throw ambiguousCoords();
332 }
333 if (file != null) {
334 throw ambiguousSource();
335 }
336 this.groupId = groupId;
337 }
338
339 /**
340 * Returns the {@code artifactId} of the POM.
341 * <p>
342 * The artifact ID is the name that uniquely identifies the project within its group,
343 * such as {@code maven-resolver-ant-tasks}.
344 * </p>
345 *
346 * <p>
347 * If this {@code Pom} is defined as a reference ({@code refid}),
348 * the value is retrieved from the referenced instance.
349 * </p>
350 *
351 * @return the artifact ID, or {@code null} if not set
352 *
353 * @see #setArtifactId(String)
354 * @see #isReference()
355 */
356 public String getArtifactId() {
357 if (isReference()) {
358 return getRef().getArtifactId();
359 }
360 return artifactId;
361 }
362
363 /**
364 * Sets the {@code artifactId} for the POM.
365 * <p>
366 * The artifact ID identifies the project within its group, for example: {@code guice}, {@code junit}, or {@code my-module}.
367 * This value is required when manually specifying the Maven coordinates (groupId, artifactId, version).
368 * </p>
369 *
370 * <p>This method must not be called if:</p>
371 * <ul>
372 * <li>{@code artifactId} was already set (directly or via {@link #setCoords(String)}),</li>
373 * <li>or if a {@code file} was specified via {@link #setFile(java.io.File)},</li>
374 * <li>or if this instance is a reference ({@code refid}).</li>
375 * </ul>
376 * <p>
377 * Violating these constraints will result in a {@link org.apache.tools.ant.BuildException}.
378 * </p>
379 *
380 * @param artifactId the Maven artifact ID
381 *
382 * @throws org.apache.tools.ant.BuildException if attributes are in conflict or not allowed
383 *
384 * @see #getArtifactId()
385 * @see #setGroupId(String)
386 * @see #setVersion(String)
387 * @see #setCoords(String)
388 * @see #setFile(java.io.File)
389 * @see #isReference()
390 */
391 public void setArtifactId(String artifactId) {
392 checkAttributesAllowed();
393 if (this.artifactId != null) {
394 throw ambiguousCoords();
395 }
396 if (file != null) {
397 throw ambiguousSource();
398 }
399 this.artifactId = artifactId;
400 }
401
402 /**
403 * Returns the {@code version} of the Maven artifact defined by this POM.
404 * <p>
405 * The version is one of the required coordinates for uniquely identifying a Maven artifact.
406 * If this object is defined as a reference ({@code refid}), the version is retrieved from the referenced instance.
407 * </p>
408 *
409 * <p>
410 * If this POM is resolved from a file and uses a {@code dependencyManagement} section (e.g. via a BOM),
411 * the version may be inherited and not explicitly required here.
412 * </p>
413 *
414 * @return the version of the artifact, or {@code null} if not set and not resolved
415 *
416 * @see #setVersion(String)
417 * @see #isReference()
418 */
419 public String getVersion() {
420 if (isReference()) {
421 return getRef().getVersion();
422 }
423 return version;
424 }
425
426 /**
427 * Sets the {@code version} of the POM.
428 * <p>
429 * This value defines the version of the project artifact being referenced,
430 * such as {@code 1.0.0} or {@code 2.5-SNAPSHOT}.
431 * </p>
432 *
433 * <p>This method must not be used if:</p>
434 * <ul>
435 * <li>{@code version} is already set (directly or via {@link #setCoords(String)}),</li>
436 * <li>a POM file is specified via {@link #setFile(java.io.File)},</li>
437 * <li>or this instance is defined as a {@code refid}.</li>
438 * </ul>
439 * <p>
440 * Violating these constraints will cause a {@link org.apache.tools.ant.BuildException}.
441 * </p>
442 *
443 * @param version the Maven version
444 *
445 * @throws org.apache.tools.ant.BuildException if attributes are in conflict or not allowed
446 *
447 * @see #getVersion()
448 * @see #setGroupId(String)
449 * @see #setArtifactId(String)
450 * @see #setCoords(String)
451 * @see #setFile(java.io.File)
452 * @see #isReference()
453 */
454 public void setVersion(String version) {
455 checkAttributesAllowed();
456 if (this.version != null) {
457 throw ambiguousCoords();
458 }
459 if (file != null) {
460 throw ambiguousSource();
461 }
462 this.version = version;
463 }
464
465 /**
466 * Returns the raw Maven coordinates string that was set via {@link #setCoords(String)}.
467 * <p>
468 * This string is typically in the format {@code groupId:artifactId:version}, but may also include
469 * optional parts such as {@code :extension} or {@code :classifier} depending on the usage context.
470 * </p>
471 *
472 * <p>
473 * If this {@code Pom} is defined as a reference ({@code refid}), the value is retrieved
474 * from the referenced instance.
475 * </p>
476 *
477 * @return the raw coordinate string, or {@code null} if not set
478 *
479 * @see #setCoords(String)
480 * @see #isReference()
481 */
482 public String getCoords() {
483 if (isReference()) {
484 return getRef().getCoords();
485 }
486 return coords;
487 }
488
489 /**
490 * Sets the Maven coordinates for this POM using a compact string format.
491 * <p>
492 * The expected format is {@code groupId:artifactId:version}, where:
493 * </p>
494 * <ul>
495 * <li>{@code groupId} is the group ID of the artifact, e.g. {@code org.apache.maven}</li>
496 * <li>{@code artifactId} is the artifact ID, e.g. {@code maven-core}</li>
497 * <li>{@code version} is the version, e.g. {@code 3.9.0}</li>
498 * </ul>
499 *
500 * <p>
501 * This method provides a concise alternative to setting each of {@link #setGroupId(String)},
502 * {@link #setArtifactId(String)}, and {@link #setVersion(String)} individually.
503 * </p>
504 *
505 * <p><b>Mutual exclusion:</b> This method must not be used in combination with:</p>
506 * <ul>
507 * <li>{@link #setGroupId(String)}, {@link #setArtifactId(String)}, or {@link #setVersion(String)}</li>
508 * <li>{@link #setFile(java.io.File)}</li>
509 * <li>{@link #setRefid(org.apache.tools.ant.types.Reference)}</li>
510 * </ul>
511 * Violating this constraint will result in a {@link org.apache.tools.ant.BuildException}.
512 *
513 * @param coords the Maven coordinates in the format {@code groupId:artifactId:version}
514 *
515 * @throws org.apache.tools.ant.BuildException if the format is invalid or attributes conflict
516 *
517 * @see #getCoords()
518 * @see #setGroupId(String)
519 * @see #setArtifactId(String)
520 * @see #setVersion(String)
521 * @see #setFile(java.io.File)
522 * @see #setRefid(org.apache.tools.ant.types.Reference)
523 */
524 public void setCoords(String coords) {
525 checkAttributesAllowed();
526 if (file != null) {
527 throw ambiguousSource();
528 }
529 if (groupId != null || artifactId != null || version != null) {
530 throw ambiguousCoords();
531 }
532 Pattern p = Pattern.compile("([^: ]+):([^: ]+):([^: ]+)");
533 Matcher m = p.matcher(coords);
534 if (!m.matches()) {
535 throw new BuildException("Bad POM coordinates, expected format is <groupId>:<artifactId>:<version>");
536 }
537 groupId = m.group(1);
538 artifactId = m.group(2);
539 version = m.group(3);
540 }
541
542 private BuildException ambiguousCoords() {
543 return new BuildException("You must not specify both 'coords' and ('groupId', 'artifactId', 'version')");
544 }
545
546 private BuildException ambiguousSource() {
547 return new BuildException(
548 "You must not specify both 'file' and " + "('coords', 'groupId', 'artifactId', 'version')");
549 }
550
551 /**
552 * Returns the packaging type of the POM, such as {@code jar}, {@code pom}, or {@code war}.
553 * <p>
554 * This value is typically set via {@link #setPackaging(String)} or resolved from a parsed POM file.
555 * If not explicitly set, the default packaging is usually {@code jar}.
556 * </p>
557 *
558 * <p>
559 * If this {@code Pom} is defined as a reference ({@code refid}),
560 * the packaging is retrieved from the referenced {@code Pom} instance.
561 * </p>
562 *
563 * @return the packaging type, or {@code null} if not set
564 *
565 * @see #setPackaging(String)
566 * @see #isReference()
567 */
568 public String getPackaging() {
569 if (isReference()) {
570 return getRef().getPackaging();
571 }
572 return packaging;
573 }
574
575 /**
576 * Sets the packaging type of the POM, such as {@code jar}, {@code war}, {@code pom}, etc.
577 * <p>
578 * This value determines how the artifact is packaged and what build lifecycle it uses.
579 * If not specified, Maven assumes a default of {@code jar}.
580 * </p>
581 *
582 * <p>
583 * This method must not be used if a POM file has been specified via {@link #setFile(java.io.File)},
584 * or if this object is defined as a reference ({@code refid}). Violating these constraints
585 * will result in a {@link org.apache.tools.ant.BuildException}.
586 * </p>
587 *
588 * @param packaging the packaging type to assign to the POM
589 *
590 * @throws org.apache.tools.ant.BuildException if attributes are in conflict or not allowed
591 *
592 * @see #getPackaging()
593 * @see #setFile(java.io.File)
594 * @see #isReference()
595 */
596 public void setPackaging(String packaging) {
597 checkAttributesAllowed();
598 if (file != null) {
599 throw ambiguousSource();
600 }
601 this.packaging = packaging;
602 }
603
604 /**
605 * Returns the internal {@link RemoteRepositories} container associated with this POM.
606 * <p>
607 * This container holds the list of remote repositories that may be used when resolving
608 * the POM from a file, including parent POMs, dependencies, and plugin artifacts.
609 * </p>
610 *
611 * <p>
612 * If the container has not been initialized yet, this method will lazily create and return it.
613 * </p>
614 *
615 * @return the {@code RemoteRepositories} instance associated with this POM
616 *
617 * @see #addRemoteRepos(RemoteRepositories)
618 * @see RemoteRepository
619 */
620 private RemoteRepositories getRemoteRepos() {
621 if (remoteRepositories == null) {
622 remoteRepositories = new RemoteRepositories();
623 remoteRepositories.setProject(getProject());
624 }
625 return remoteRepositories;
626 }
627
628 /**
629 * Adds a single remote repository to this POM's list of repositories.
630 * <p>
631 * These repositories are used when resolving artifacts related to this POM,
632 * such as parent POMs or dependencies, especially when the POM is loaded from a file.
633 * </p>
634 *
635 * <p>
636 * This method delegates to {@link #getRemoteRepos()} and appends the given
637 * {@link RemoteRepository} to the internal {@link RemoteRepositories} container.
638 * </p>
639 *
640 * @param repository the remote repository to add
641 *
642 * @see #getRemoteRepos()
643 * @see RemoteRepository
644 * @see RemoteRepositories
645 */
646 public void addRemoteRepo(RemoteRepository repository) {
647 getRemoteRepos().addRemoterepo(repository);
648 }
649
650 /**
651 * Adds a {@link RemoteRepositories} container to this POM, which holds one or more remote repositories
652 * used to resolve dependencies and parent POMs when the POM is loaded from a file.
653 * <p>
654 * This method delegates to {@link #getRemoteRepos()} and appends the given repository container
655 * to the list of remote repositories associated with this POM.
656 * </p>
657 *
658 * @param repositories a container of remote repositories to add
659 *
660 * @see #getRemoteRepos()
661 * @see RemoteRepositories#addRemoterepos(RemoteRepositories)
662 * @see RemoteRepository
663 */
664 public void addRemoteRepos(RemoteRepositories repositories) {
665 getRemoteRepos().addRemoterepos(repositories);
666 }
667
668 /**
669 * Adds a reference to a {@link RemoteRepositories} instance to this POM's list of remote repositories.
670 * <p>
671 * This allows remote repositories to be defined elsewhere in the build script and referenced by ID,
672 * promoting reuse and separation of concerns.
673 * </p>
674 *
675 * <p>
676 * Internally, this method creates a new {@code RemoteRepositories} object, sets the reference ID,
677 * and delegates to {@link #getRemoteRepos()} to append it to the list.
678 * </p>
679 *
680 * @param ref the Ant {@code Reference} to a {@code RemoteRepositories} definition
681 *
682 * @see RemoteRepositories
683 * @see #addRemoteRepos(RemoteRepositories)
684 * @see #getRemoteRepos()
685 */
686 public void setRemoteReposRef(Reference ref) {
687 RemoteRepositories repos = new RemoteRepositories();
688 repos.setProject(getProject());
689 repos.setRefid(ref);
690 getRemoteRepos().addRemoterepos(repos);
691 }
692
693 /**
694 * Returns the parsed Maven {@link org.apache.maven.model.Model} associated with this POM.
695 * <p>
696 * If a {@code file} has been specified via {@link #setFile(java.io.File)},
697 * the model is lazily loaded and cached using the {@link AntRepoSys} instance
698 * for the current Ant {@link org.apache.tools.ant.Project}. If no file is set,
699 * this method returns {@code null}.
700 * </p>
701 *
702 * <p>
703 * If this {@code Pom} is defined as a reference ({@code refid}),
704 * the model is retrieved from the referenced {@code Pom} instance.
705 * </p>
706 *
707 * <p>
708 * This method is thread-safe and performs lazy loading: the model is loaded only once
709 * and reused on subsequent calls.
710 * </p>
711 *
712 * @param task the Ant task context used for logging and error reporting during model loading
713 * @return the Maven {@code Model} parsed from the specified POM file, or {@code null} if no file was set
714 *
715 * @see #setFile(java.io.File)
716 * @see #isReference()
717 * @see org.apache.maven.model.Model
718 */
719 public Model getModel(Task task) {
720 if (isReference()) {
721 return getRef().getModel(task);
722 }
723 synchronized (this) {
724 if (model == null) {
725 if (file != null) {
726 model = AntRepoSys.getInstance(getProject()).loadModel(task, file, true, remoteRepositories);
727 }
728 }
729 return model;
730 }
731 }
732
733 @Override
734 public void execute() {
735 validate();
736
737 if (file != null && (id == null || AntRepoSys.getInstance(getProject()).getDefaultPom() == null)) {
738 AntRepoSys.getInstance(getProject()).setDefaultPom(this);
739 }
740
741 ProjectWorkspaceReader.getInstance().addPom(this);
742
743 Model model = getModel(this);
744
745 if (model == null) {
746 coords = getGroupId() + ":" + getArtifactId() + ":" + getVersion();
747 return;
748 }
749
750 coords = model.getGroupId() + ":" + model.getArtifactId() + ":" + model.getVersion();
751
752 ModelValueExtractor extractor = new ModelValueExtractor(id, model, getProject());
753
754 PropertyHelper propHelper = PropertyHelper.getPropertyHelper(getProject());
755
756 try {
757 // Ant 1.8.0 delegate
758 PomPropertyEvaluator.register(extractor, propHelper);
759 } catch (LinkageError e) {
760 // Ant 1.6 - 1.7.1 interceptor chaining
761 PomPropertyHelper.register(extractor, propHelper);
762 }
763 }
764
765 @Override
766 public String toString() {
767 return coords + " (" + super.toString() + ")";
768 }
769 }