View Javadoc
1   /*
2    * Licensed under the Apache License, Version 2.0 (the "License");
3    * you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at
5    *
6    * http://www.apache.org/licenses/LICENSE-2.0
7    *
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS,
10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   * See the License for the specific language governing permissions and
12   * limitations under the License.
13   */
14  
15  package org.basepom.mojo.propertyhelper;
16  
17  import static com.google.common.base.Preconditions.checkNotNull;
18  import static com.google.common.base.Preconditions.checkState;
19  
20  import org.basepom.mojo.propertyhelper.beans.DateDefinition;
21  import org.basepom.mojo.propertyhelper.beans.IgnoreWarnFail;
22  import org.basepom.mojo.propertyhelper.beans.MacroDefinition;
23  import org.basepom.mojo.propertyhelper.beans.NumberDefinition;
24  import org.basepom.mojo.propertyhelper.beans.PropertyGroup;
25  import org.basepom.mojo.propertyhelper.beans.StringDefinition;
26  import org.basepom.mojo.propertyhelper.beans.UuidDefinition;
27  import org.basepom.mojo.propertyhelper.macros.MacroType;
28  import org.basepom.mojo.propertyhelper.util.Log;
29  
30  import java.io.File;
31  import java.io.IOException;
32  import java.util.AbstractMap.SimpleImmutableEntry;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.Map.Entry;
36  import java.util.Optional;
37  import java.util.Set;
38  import javax.annotation.CheckForNull;
39  import javax.inject.Inject;
40  
41  import com.google.common.collect.ImmutableList;
42  import com.google.common.collect.ImmutableList.Builder;
43  import com.google.common.collect.ImmutableMap;
44  import com.google.common.collect.Maps;
45  import com.google.common.collect.Sets;
46  import org.apache.maven.plugin.AbstractMojo;
47  import org.apache.maven.plugin.MojoExecutionException;
48  import org.apache.maven.plugins.annotations.Parameter;
49  import org.apache.maven.project.MavenProject;
50  import org.apache.maven.settings.Settings;
51  
52  /**
53   * Base code for all the mojos.
54   */
55  public abstract class AbstractPropertyHelperMojo
56          extends AbstractMojo {
57  
58      protected static final Log LOG = Log.findLog();
59      protected final ValueCache valueCache = new ValueCache();
60      private final Map<String, String> values = Maps.newHashMap();
61  
62      /**
63       * Defines the action to take if a property is present multiple times.
64       */
65      @Parameter(defaultValue = "fail")
66      public String onDuplicateProperty = "fail";
67  
68      /**
69       * Defines the action to take if a referenced property is missing.
70       */
71      @Parameter(defaultValue = "fail")
72      public String onMissingProperty = "fail";
73  
74      /**
75       * List of the property group ids to activate for a plugin execution.
76       */
77      @Parameter
78      public String[] activeGroups = new String[0];
79  
80      /**
81       * List of available property groups. A property group contains one or more property definitions and must be activated with activeGroups.
82       */
83      @Parameter
84      public PropertyGroup[] propertyGroups = new PropertyGroup[0];
85  
86      /**
87       * Number property definitions.
88       */
89      @Parameter
90      public NumberDefinition[] numbers = new NumberDefinition[0];
91  
92      /**
93       * String property definitions.
94       */
95      @Parameter
96      public StringDefinition[] strings = new StringDefinition[0];
97  
98      /**
99       * Date property definitions.
100      */
101     @Parameter
102     public DateDefinition[] dates = new DateDefinition[0];
103 
104     /**
105      * Macro definitions.
106      */
107     @Parameter
108     public MacroDefinition[] macros = new MacroDefinition[0];
109 
110     /**
111      * Uuid definitions.
112      */
113     @Parameter
114     public UuidDefinition[] uuids = new UuidDefinition[0];
115 
116     /**
117      * The maven project (effective pom).
118      */
119     @Parameter(defaultValue = "${project}", readonly = true)
120     public MavenProject project;
121     @Parameter(defaultValue = "${settings}", readonly = true)
122     public Settings settings;
123 
124     @Parameter(required = true, readonly = true, defaultValue = "${project.basedir}")
125     public File basedir;
126     /**
127      * If set to true, goal execution is skipped.
128      */
129     @Parameter(defaultValue = "false")
130     boolean skip;
131     public List<NumberField> numberFields = null;
132 
133     @Inject
134     public Map<String, MacroType> macroMap = null;
135 
136     private boolean isSnapshot;
137 
138     @Override
139     public void execute()
140             throws MojoExecutionException {
141         isSnapshot = project.getArtifact().isSnapshot();
142         LOG.debug("Project is a %s.", isSnapshot ? "snapshot" : "release");
143         LOG.trace("%s on duplicate, %s on missing", onDuplicateProperty, onMissingProperty);
144 
145         try {
146             if (skip) {
147                 LOG.debug("Skipping execution!");
148             } else {
149                 doExecute();
150             }
151         } catch (IOException e) {
152             throw new MojoExecutionException("While running mojo: ", e);
153         } finally {
154             LOG.debug("Ended %s mojo run!", this.getClass().getSimpleName());
155         }
156     }
157 
158     public MavenProject getProject() {
159         checkNotNull(project, "project is null");
160         return project;
161     }
162 
163     public Settings getSettings() {
164         checkNotNull(settings, "settings is null");
165         return settings;
166     }
167 
168     public File getBasedir() {
169         checkNotNull(basedir, "basedir is null");
170         return basedir;
171     }
172 
173     public Map<String, MacroType> getMacros() {
174         checkNotNull(macroMap, "macroMap is null");
175         return macroMap;
176     }
177 
178     @CheckForNull
179     public List<NumberField> getNumbers() {
180         return numberFields;
181     }
182 
183     /**
184      * Subclasses need to implement this method.
185      */
186     protected abstract void doExecute() throws IOException, MojoExecutionException;
187 
188     protected void loadPropertyElements() throws MojoExecutionException, IOException {
189         final Builder<PropertyElement> propertyElements = ImmutableList.builder();
190 
191         numberFields = NumberField.createNumbers(valueCache, numbers);
192         propertyElements.addAll(numberFields);
193         propertyElements.addAll(StringField.createStrings(valueCache, strings));
194         propertyElements.addAll(DateField.createDates(valueCache, dates));
195         propertyElements.addAll(MacroField.createMacros(valueCache, macros, this));
196         propertyElements.addAll(UuidField.createUuids(valueCache, uuids));
197 
198         for (final PropertyElement pe : propertyElements.build()) {
199             final Optional<String> value = pe.getPropertyValue();
200             values.put(pe.getPropertyName(), value.orElse(null));
201 
202             if (pe.isExport()) {
203                 final String result = value.orElse("");
204                 project.getProperties().setProperty(pe.getPropertyName(), result);
205                 LOG.debug("Exporting Property name: %s, value: %s", pe.getPropertyName(), result);
206             } else {
207                 LOG.debug("Property name: %s, value: %s", pe.getPropertyName(),
208                         value.orElse("<null>"));
209             }
210         }
211 
212         // Now generate the property groups.
213         final ImmutableMap.Builder<String, Entry<PropertyGroup, List<PropertyElement>>> builder = ImmutableMap.builder();
214 
215         final Set<String> propertyNames = Sets.newHashSet();
216 
217         if (propertyGroups != null) {
218             for (final PropertyGroup propertyGroup : propertyGroups) {
219                 final List<PropertyElement> propertyFields = PropertyField.createProperties(project.getModel(), values, propertyGroup);
220                 builder.put(propertyGroup.getId(), new SimpleImmutableEntry<>(propertyGroup, propertyFields));
221             }
222         }
223 
224         final Map<String, Entry<PropertyGroup, List<PropertyElement>>> propertyPairs = builder.build();
225 
226         if (activeGroups != null) {
227             for (final String activeGroup : activeGroups) {
228                 final Entry<PropertyGroup, List<PropertyElement>> propertyElement = propertyPairs.get(activeGroup);
229                 checkState(propertyElement != null, "activated group '%s' does not exist", activeGroup);
230 
231                 final PropertyGroup propertyGroup = propertyElement.getKey();
232                 if ((propertyGroup.isActiveOnRelease() && !isSnapshot) || (propertyGroup.isActiveOnSnapshot() && isSnapshot)) {
233                     for (final PropertyElement pe : propertyElement.getValue()) {
234                         final Optional<String> value = pe.getPropertyValue();
235                         final String propertyName = pe.getPropertyName();
236                         IgnoreWarnFail.checkState(propertyGroup.getOnDuplicateProperty(), !propertyNames.contains(propertyName),
237                                 "property name '" + propertyName + "'");
238                         propertyNames.add(propertyName);
239 
240                         project.getProperties().setProperty(propertyName, value.orElse(""));
241                     }
242                 } else {
243                     LOG.debug("Skipping property group %s: Snapshot: %b, activeOnSnapshot: %b, activeOnRelease: %b", activeGroup, isSnapshot,
244                             propertyGroup.isActiveOnSnapshot(), propertyGroup.isActiveOnRelease());
245                 }
246             }
247         }
248     }
249 }