View Javadoc
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  
23  import org.apache.maven.resolver.internal.ant.AntRepoSys;
24  import org.apache.tools.ant.Project;
25  import org.apache.tools.ant.Task;
26  import org.apache.tools.ant.types.DataType;
27  import org.apache.tools.ant.types.Reference;
28  
29  /**
30   * Represents a custom local Maven repository location in an Ant build script.
31   * <p>
32   * This Ant {@code DataType} allows you to override the default local repository
33   * (typically {@code ~/.m2/repository}) by specifying a custom directory to be used
34   * for dependency resolution, artifact installation, or deployment.
35   * </p>
36   *
37   * <p>
38   * The local repository directory is specified using the {@code dir} attribute.
39   * This can be declared inline or via a shared reference using {@code refid}.
40   * </p>
41   *
42   * <h2>Usage Example:</h2>
43   * <pre>{@code
44   * <localRepository id="custom.repo" dir="target/local-repo"/>
45   *
46   * <resolve>
47   *   <localRepo refid="custom.repo"/>
48   *   ...
49   * </resolve>
50   * }</pre>
51   *
52   * <h2>Attributes:</h2>
53   * <ul>
54   *   <li><strong>dir</strong> — the directory to use as the local repository (required unless using {@code refid})</li>
55   * </ul>
56   *
57   * <p>
58   * If this type is declared without a {@link org.apache.tools.ant.Task} context,
59   * it will automatically register itself with the current project via {@link AntRepoSys#setLocalRepository(LocalRepository)}.
60   * </p>
61   *
62   * <h2>Typical Use Cases:</h2>
63   * <ul>
64   *   <li>Using an isolated local repository for reproducible builds</li>
65   *   <li>Testing against a temporary or project-scoped repository</li>
66   *   <li>Ensuring deployment and resolution do not affect the user's global Maven state</li>
67   * </ul>
68   *
69   * @see #setDir(File)
70   * @see #setRefid(org.apache.tools.ant.types.Reference)
71   * @see org.apache.maven.resolver.internal.ant.tasks.Resolve
72   * @see org.apache.maven.resolver.internal.ant.AntRepoSys
73   */
74  public class LocalRepository extends DataType {
75  
76      private final Task task;
77  
78      private File dir;
79  
80      /**
81       * Constructs a new {@code LocalRepository} without an owning Ant task.
82       * <p>
83       * This constructor is typically used when the local repository is defined inline
84       * in the build script, allowing it to be automatically registered with the project.
85       * </p>
86       */
87      public LocalRepository() {
88          this(null);
89      }
90  
91      /**
92       * Constructs a new {@code LocalRepository} with an owning Ant task.
93       * <p>
94       * This constructor is used when the local repository is defined within a specific
95       * Ant task context, allowing it to be associated with that task.
96       * </p>
97       *
98       * @param task the Ant task that owns this {@code LocalRepository}, or {@code null} if not associated with a task
99       */
100     public LocalRepository(Task task) {
101         this.task = task;
102     }
103 
104     /**
105      * Sets the Ant project context for this {@code LocalRepository}.
106      * <p>
107      * In addition to the standard behavior of associating this data type with the Ant project,
108      * this method also automatically registers this {@code LocalRepository} with the global
109      * {@link org.apache.maven.resolver.internal.ant.AntRepoSys} instance for the project,
110      * <strong>but only if no owning {@link org.apache.tools.ant.Task} was provided</strong>.
111      * </p>
112      *
113      * <p>
114      * This automatic registration allows this local repository to become the default
115      * used for resolution and deployment tasks within the current build context.
116      * </p>
117      *
118      * @param project the Ant project to associate with this data type
119      *
120      * @see org.apache.maven.resolver.internal.ant.AntRepoSys#setLocalRepository(LocalRepository)
121      * @see #LocalRepository(org.apache.tools.ant.Task)
122      */
123     @Override
124     public void setProject(Project project) {
125         super.setProject(project);
126 
127         if (task == null) {
128             AntRepoSys.getInstance(project).setLocalRepository(this);
129         }
130     }
131 
132     /**
133      * Resolves this object if defined as a reference and verifies that it is a
134      * {@code LocalRepository} instance.
135      *
136      * @return the referenced {@code LocalRepository} instance
137      * @throws org.apache.tools.ant.BuildException if the reference is invalid
138      *
139      * @see #setRefid(org.apache.tools.ant.types.Reference)
140      * @see #isReference()
141      */
142     protected LocalRepository getRef() {
143         return getCheckedRef(LocalRepository.class);
144     }
145 
146     /**
147      * Sets a reference to another {@code <localRepository>} definition.
148      * <p>
149      * This allows the current {@code LocalRepository} to act as an alias
150      * for another local repository definition declared elsewhere in the build script.
151      * When a reference is set, all other attributes (such as {@code dir}) must remain unset.
152      * </p>
153      *
154      * <p>
155      * Attempting to set this reference after the {@code dir} attribute has already been specified
156      * will result in an error.
157      * </p>
158      *
159      * @param ref the reference to another {@code LocalRepository}
160      *
161      * @throws org.apache.tools.ant.BuildException if {@code dir} is already set
162      *
163      * @see #getRef()
164      * @see #setDir(File)
165      */
166     @Override
167     public void setRefid(Reference ref) {
168         if (dir != null) {
169             throw tooManyAttributes();
170         }
171         super.setRefid(ref);
172     }
173 
174     /**
175      * Returns the directory to be used as the local Maven repository.
176      * <p>
177      * If this {@code LocalRepository} is defined as a reference (via {@code refid}),
178      * the method delegates to the referenced instance.
179      * </p>
180      *
181      * @return the local repository directory, or {@code null} if not set
182      *
183      * @see #setDir(File)
184      * @see #setRefid(org.apache.tools.ant.types.Reference)
185      */
186     public File getDir() {
187         if (isReference()) {
188             return getRef().getDir();
189         }
190         return dir;
191     }
192 
193     /**
194      * Sets the directory to be used as the local Maven repository.
195      * <p>
196      * This directory will be used in place of the default {@code ~/.m2/repository}
197      * for tasks such as dependency resolution, artifact installation, and deployment.
198      * </p>
199      *
200      * <p>
201      * This method may not be used if this object is defined as a reference (i.e., {@code refid} is set).
202      * If the attributes are already configured, an exception will be thrown.
203      * </p>
204      *
205      * @param dir the directory to use as the local repository
206      *
207      * @throws org.apache.tools.ant.BuildException if this instance is a reference or attributes are not allowed
208      *
209      * @see #getDir()
210      * @see #setRefid(org.apache.tools.ant.types.Reference)
211      */
212     public void setDir(File dir) {
213         checkAttributesAllowed();
214         this.dir = dir;
215     }
216 }