001package org.andromda.maven.plugin.andromdapp; 002 003import java.io.File; 004import java.io.IOException; 005import java.io.StringReader; 006import java.net.URL; 007import java.util.List; 008import java.util.Properties; 009import org.andromda.core.common.ResourceUtils; 010import org.apache.commons.lang.ObjectUtils; 011import org.apache.commons.lang.StringUtils; 012import org.apache.maven.plugin.AbstractMojo; 013import org.apache.maven.plugin.MojoExecutionException; 014import org.apache.maven.project.MavenProject; 015import org.apache.maven.settings.Settings; 016import org.apache.maven.shared.filtering.PropertyUtils; 017import org.codehaus.plexus.util.InterpolationFilterReader; 018 019/** 020 * The abstract AndroMDAapp mojo (this should be extended by any Mojo that 021 * executes AndroMDApp. 022 * 023 * @author Chad Brandon 024 * @author Bob Fields 025 */ 026public abstract class AbstractAndroMDAppMojo 027 extends AbstractMojo 028{ 029 /** 030 * The URI to an optional AndroMDApp configuration file. 031 * 032 * @parameter expression="${configuration.uri}" 033 */ 034 private String configurationUri; 035 036 /** 037 * @parameter expression="${project}" 038 * @required 039 * @readonly 040 */ 041 private MavenProject project; 042 043 /** 044 * The current user system settings for use in Maven. (allows us to pass the user 045 * settings to the AndroMDA configuration). 046 * 047 * @parameter expression="${settings}" 048 * @required 049 * @readonly 050 */ 051 protected Settings settings; 052 053 /** 054 * @parameter expression="${project.build.filters}" 055 */ 056 protected List<String> propertyFiles; 057 058 /** 059 * Set this to 'true' to bypass cartridge tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion. 060 * 061 * @parameter expression="${maven.test.skip}" 062 */ 063 protected boolean skip; 064 065 /** 066 * Set this to 'true' to skip running tests, but still compile them. Its use is NOT RECOMMENDED, but quite convenient on occasion. 067 * 068 * @parameter expression="${skipTests}" 069 */ 070 protected boolean skipTests; 071 072 /** 073 * Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on occasion. 074 * 075 * @parameter expression="${maven.test.failure.ignore}" default-value="false" 076 */ 077 protected boolean testFailureIgnore; 078 079 /** 080 * Whether or not processing should be skipped (this is if you want to completely skip code generation, i.e. if 081 * code is already generated and you are creating the site from already generated source code). 082 * 083 * @parameter expression="${andromdapp.run.skip}" 084 */ 085 protected boolean skipProcessing = false; 086 087 /** 088 * Collects and returns all properties as a Properties instance. 089 * 090 * @return the properties including those from the project, settings, etc. 091 * @throws IOException 092 */ 093 private Properties getProperties() 094 throws IOException 095 { 096 // System properties 097 final Properties properties = new Properties(); 098 099 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}