1 package org.andromda.maven.plugin.andromdapp;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.StringReader;
6 import java.net.URL;
7 import java.util.List;
8 import java.util.Properties;
9 import org.andromda.core.common.ResourceUtils;
10 import org.apache.commons.lang.ObjectUtils;
11 import org.apache.commons.lang.StringUtils;
12 import org.apache.maven.plugin.AbstractMojo;
13 import org.apache.maven.plugin.MojoExecutionException;
14 import org.apache.maven.project.MavenProject;
15 import org.apache.maven.settings.Settings;
16 import org.apache.maven.shared.filtering.PropertyUtils;
17 import org.codehaus.plexus.util.InterpolationFilterReader;
18
19 /**
20 * The abstract AndroMDAapp mojo (this should be extended by any Mojo that
21 * executes AndroMDApp.
22 *
23 * @author Chad Brandon
24 * @author Bob Fields
25 */
26 public abstract class AbstractAndroMDAppMojo
27 extends AbstractMojo
28 {
29 /**
30 * The URI to an optional AndroMDApp configuration file.
31 *
32 * @parameter expression="${configuration.uri}"
33 */
34 private String configurationUri;
35
36 /**
37 * @parameter expression="${project}"
38 * @required
39 * @readonly
40 */
41 private MavenProject project;
42
43 /**
44 * The current user system settings for use in Maven. (allows us to pass the user
45 * settings to the AndroMDA configuration).
46 *
47 * @parameter expression="${settings}"
48 * @required
49 * @readonly
50 */
51 protected Settings settings;
52
53 /**
54 * @parameter expression="${project.build.filters}"
55 */
56 protected List<String> propertyFiles;
57
58 /**
59 * Set this to 'true' to bypass cartridge tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.
60 *
61 * @parameter expression="${maven.test.skip}"
62 */
63 protected boolean skip;
64
65 /**
66 * Set this to 'true' to skip running tests, but still compile them. Its use is NOT RECOMMENDED, but quite convenient on occasion.
67 *
68 * @parameter expression="${skipTests}"
69 */
70 protected boolean skipTests;
71
72 /**
73 * Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on occasion.
74 *
75 * @parameter expression="${maven.test.failure.ignore}" default-value="false"
76 */
77 protected boolean testFailureIgnore;
78
79 /**
80 * Whether or not processing should be skipped (this is if you want to completely skip code generation, i.e. if
81 * code is already generated and you are creating the site from already generated source code).
82 *
83 * @parameter expression="${andromdapp.run.skip}"
84 */
85 protected boolean skipProcessing = false;
86
87 /**
88 * Collects and returns all properties as a Properties instance.
89 *
90 * @return the properties including those from the project, settings, etc.
91 * @throws IOException
92 */
93 private Properties getProperties()
94 throws IOException
95 {
96 // System properties
97 final Properties properties = new Properties();
98
99 properties.put(
100 "settings",
101 this.settings);
102
103 // - project properties
104 properties.putAll(this.project.getProperties());
105 if (this.propertyFiles != null)
106 {
107 for (final String propertiesFile : this.propertyFiles)
108 {
109 final Properties projectProperties = PropertyUtils.loadPropertyFile(
110 new File(propertiesFile),
111 true,
112 true);
113 properties.putAll(projectProperties);
114 }
115 }
116
117 for (final Object propertyObject : properties.keySet())
118 {
119 final String property = (String)propertyObject;
120 final String value = this.replaceProperties(properties, ObjectUtils.toString(properties.get(property)));
121 properties.put(property, value);
122 }
123
124 properties.putAll(System.getProperties());
125
126 return properties;
127 }
128
129 /**
130 * Replaces all properties having the style
131 * <code>${some.property}</code> with the value
132 * of the specified property if there is one.
133 *
134 * @param string the string to perform replacement on.
135 * @return this.replaceProperties(this.getProperties(), string);
136 * @throws IOException
137 */
138 protected String replaceProperties(final String string)
139 throws IOException
140 {
141 return this.replaceProperties(this.getProperties(), string);
142 }
143
144 /**
145 * Retrieves the interpolated {#configurationUri} contents as a String.
146 *
147 * @return the contents of the configuration as a string.
148 * @throws MojoExecutionException
149 * @throws IOException
150 */
151 protected String getConfigurationContents() throws MojoExecutionException, IOException
152 {
153 String contents = null;
154 if (StringUtils.isNotBlank(this.configurationUri))
155 {
156 final URL configuration = ResourceUtils.toURL(this.configurationUri);
157 if (configuration == null)
158 {
159 throw new MojoExecutionException("No configuration could be loaded from --> '" + this.configurationUri + '\'');
160 }
161 contents = this.replaceProperties(ResourceUtils.getContents(configuration));
162 }
163 return contents;
164 }
165
166 /**
167 * The begin token for interpolation (we need it different
168 * than what Maven uses so that Maven variables aren't replaced).
169 */
170 private static final String BEGIN_TOKEN = "$${";
171
172 /**
173 * The end token for interpolation.
174 */
175 private static final String END_TOKEN = "}";
176
177 /**
178 * Replaces all properties having the style
179 * <code>${some.property}</code> with the value
180 * of the specified property if there is one.
181 *
182 * @param properties the properties used to perform the replacement.
183 * @param string the fileContents to perform replacement on.
184 */
185 @SuppressWarnings("resource")
186 private String replaceProperties(final Properties properties, final String string) throws IOException
187 {
188 String replacement = null;
189 final StringReader stringReader = new StringReader(string);
190 InterpolationFilterReader reader = new InterpolationFilterReader(stringReader, properties, "${", "}");
191 reader.reset();
192 try
193 {
194 reader = new InterpolationFilterReader(
195 reader,
196 new BeanProperties(this.project),
197 BEGIN_TOKEN,
198 END_TOKEN);
199 reader = new InterpolationFilterReader(
200 reader,
201 new BeanProperties(this.project),
202 BEGIN_TOKEN,
203 END_TOKEN);
204 replacement = ResourceUtils.getContents(reader);
205 }
206 finally
207 {
208 reader.close();
209 }
210 return replacement;
211 }
212
213 }