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.util.ArrayList;
22 import java.util.List;
23
24 import org.apache.tools.ant.Task;
25 import org.apache.tools.ant.types.DataType;
26 import org.apache.tools.ant.types.Reference;
27
28 /**
29 * A container for one or more {@link Artifact} elements in an Ant build script.
30 * <p>
31 * This Ant {@link org.apache.tools.ant.types.DataType} is used to group multiple artifacts,
32 * allowing them to be referenced collectively by tasks such as
33 * {@link org.apache.maven.resolver.internal.ant.tasks.Install Install} or
34 * {@link org.apache.maven.resolver.internal.ant.tasks.Deploy Deploy}.
35 * </p>
36 *
37 * <h2>Usage Example:</h2>
38 * <pre>{@code
39 * <repo:artifacts id="deployment.artifacts">
40 * <repo:artifact file="target/my-lib.jar" type="jar" groupId="com.example" artifactId="my-lib" version="1.0.0"/>
41 * <repo:artifact file="target/my-lib.pom" type="pom" groupId="com.example" artifactId="my-lib" version="1.0.0"/>
42 * </repo:artifacts>
43 *
44 * <repo:deploy artifactsRef="deployment.artifacts"/>
45 * }</pre>
46 *
47 * <h2>Attributes:</h2>
48 * <ul>
49 * <li><strong>id</strong> — Optional reference ID to reuse the container via {@code artifactsRef}.</li>
50 * </ul>
51 *
52 * <h2>Nested Elements:</h2>
53 * <ul>
54 * <li>{@code <artifact>} — A single Maven artifact definition.</li>
55 * <li>{@code <artifacts>} — Another nested {@code Artifacts} element, allowing composition.</li>
56 * </ul>
57 *
58 * <p>This class also supports Ant references via {@code refid}, and prevents combining that
59 * with nested artifact declarations.</p>
60 *
61 * @see Artifact
62 * @see ArtifactContainer
63 * @see org.apache.maven.resolver.internal.ant.tasks.Install
64 * @see org.apache.maven.resolver.internal.ant.tasks.Deploy
65 */
66 public class Artifacts extends DataType implements ArtifactContainer {
67
68 private final List<ArtifactContainer> containers = new ArrayList<>();
69
70 /**
71 * Default constructor for the {@code Artifacts} data type.
72 */
73 public Artifacts() {
74 // Default constructor
75 }
76
77 /**
78 * Resolves this object if defined as a reference and verifies that it is a
79 * {@code Artifacts} instance.
80 *
81 * @return the referenced {@code Artifacts} instance
82 * @throws org.apache.tools.ant.BuildException if the reference is invalid
83 */
84 protected Artifacts getRef() {
85 return getCheckedRef(Artifacts.class);
86 }
87
88 /**
89 * Validates the nested artifact containers.
90 * If this is a reference, delegates to the referenced object.
91 *
92 * @param task the Ant task using this data type
93 * @throws org.apache.tools.ant.BuildException if validation fails
94 */
95 @Override
96 public void validate(Task task) {
97 if (isReference()) {
98 getRef().validate(task);
99 } else {
100 for (ArtifactContainer container : containers) {
101 container.validate(task);
102 }
103 }
104 }
105
106 /**
107 * Sets a reference to another {@code Artifacts} instance.
108 *
109 * @param ref the Ant reference
110 * @throws org.apache.tools.ant.BuildException if nested artifacts are already defined
111 */
112 @Override
113 public void setRefid(Reference ref) {
114 if (!containers.isEmpty()) {
115 throw noChildrenAllowed();
116 }
117 super.setRefid(ref);
118 }
119
120 /**
121 * Allow Ant to add a single {@link Artifact} element to this container.
122 *
123 * @param artifact the artifact to add
124 */
125 public void addArtifact(Artifact artifact) {
126 checkChildrenAllowed();
127 containers.add(artifact);
128 }
129
130 /**
131 * Allow Ant to add another {@link Artifacts} container as a nested element.
132 *
133 * @param artifacts the nested container to add
134 * @throws org.apache.tools.ant.BuildException if a circular reference is detected
135 */
136 public void addArtifacts(Artifacts artifacts) {
137 checkChildrenAllowed();
138 if (artifacts == this) {
139 throw circularReference();
140 }
141 containers.add(artifacts);
142 }
143
144 /**
145 * Collects all {@link Artifact} objects from this container and any nested containers.
146 *
147 * @return a list of all artifacts
148 */
149 @Override
150 public List<Artifact> getArtifacts() {
151 if (isReference()) {
152 return getRef().getArtifacts();
153 }
154 List<Artifact> artifacts = new ArrayList<>();
155 for (ArtifactContainer container : containers) {
156 artifacts.addAll(container.getArtifacts());
157 }
158 return artifacts;
159 }
160 }