001/* 002 * jDTAUS Core Resource Mojo 003 * Copyright (C) 2005 Christian Schulte 004 * <cs@schulte.it> 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2.1 of the License, or any later version. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 019 * 020 */ 021package org.jdtaus.mojo.resource; 022 023import java.io.File; 024import java.io.FileInputStream; 025import java.io.FileOutputStream; 026import java.io.FileWriter; 027import java.io.InputStream; 028import java.io.OutputStream; 029import java.io.OutputStreamWriter; 030import java.io.Writer; 031import java.text.DateFormat; 032import java.text.MessageFormat; 033import java.util.Date; 034import java.util.Iterator; 035import java.util.Map; 036import java.util.Properties; 037import java.util.ResourceBundle; 038import org.apache.maven.model.Resource; 039import org.apache.maven.plugin.AbstractMojo; 040import org.apache.maven.plugin.MojoExecutionException; 041import org.apache.maven.plugin.MojoFailureException; 042import org.apache.maven.project.MavenProject; 043import org.jdtaus.mojo.resource.model.Implementation; 044import org.jdtaus.mojo.resource.model.Message; 045import org.jdtaus.mojo.resource.model.ModelManager; 046import org.jdtaus.mojo.resource.model.Module; 047import org.jdtaus.mojo.resource.model.Text; 048import org.jdtaus.mojo.resource.util.BundleGenerator; 049 050/** 051 * Mojo to generate java resource accessor classes backed by java 052 * <code>ResourceBundle</code>s from a project's module descriptor. 053 * 054 * @goal java-resources 055 * @phase generate-sources 056 * @requiresDependencyResolution compile 057 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 058 * @version $JDTAUS: JavaResourcesMojo.java 8743 2012-10-07 03:06:20Z schulte $ 059 */ 060public class JavaResourcesMojo extends AbstractMojo 061{ 062 //--JavaResourcesMojo------------------------------------------------------- 063 064 /** 065 * Currently executed <code>MavenProject</code>. 066 * 067 * @parameter expression="${project}" 068 * @required 069 */ 070 private MavenProject project; 071 072 /** 073 * The directory to generate sources to. 074 * 075 * @parameter expression="${project.build.directory}/generated-sources/java-resources" 076 */ 077 private File sourceDirectory; 078 079 /** 080 * The directory to generate resources to. 081 * 082 * @parameter expression="${project.build.directory}/generated-resources/java-resources" 083 */ 084 private File resourceDirectory; 085 086 /** 087 * The directory to use for storing hashes for already generated files. 088 * 089 * @parameter expression="${project.build.directory}/java-resources" 090 */ 091 private File buildDirectory; 092 093 /** 094 * Project module descriptor to control the mojo. 095 * @parameter expression="${javaResources.moduleDescriptor}" 096 * default-value="src/main/resources/META-INF/jdtaus/module.xml" 097 */ 098 private File moduleDescriptor; 099 100 /** 101 * The encoding to use for writing sources. 102 * @parameter expression="${project.build.sourceEncoding}" 103 */ 104 private String encoding; 105 106 /** 107 * The default language for generated bundles. 108 * @parameter expression="${javaResources.defaultLanguage}" 109 * default-value="en" 110 */ 111 private String defaultLanguage; 112 113 /** @component */ 114 private BundleGenerator generator; 115 116 /** @component */ 117 private ModelManager modelManager; 118 119 /** Creates a new {@code JavaResourcesMojo} instance. */ 120 public JavaResourcesMojo() 121 { 122 super(); 123 } 124 125 private MavenProject getProject() 126 { 127 return this.project; 128 } 129 130 private File getSourceDirectory() 131 { 132 return this.sourceDirectory; 133 } 134 135 private File getResourceDirectory() 136 { 137 return this.resourceDirectory; 138 } 139 140 private File getBuildDirectory() 141 { 142 return this.buildDirectory; 143 } 144 145 private BundleGenerator getBundleGenerator() 146 { 147 return this.generator; 148 } 149 150 private ModelManager getModelManager() 151 { 152 return this.modelManager; 153 } 154 155 private File getModuleDescriptor() 156 { 157 return this.moduleDescriptor; 158 } 159 160 private String getEncoding() 161 { 162 return this.encoding; 163 } 164 165 private String getDefaultLanguage() 166 { 167 return this.defaultLanguage; 168 } 169 170 public void execute() throws MojoExecutionException, MojoFailureException 171 { 172 if ( !this.getModuleDescriptor().exists() ) 173 { 174 throw new MojoExecutionException( 175 this.getMessage( "fileNotFound" ). 176 format( new Object[] 177 { 178 this.getModuleDescriptor().getAbsolutePath() 179 } ) ); 180 181 } 182 183 try 184 { 185 this.assertDirectoryExistence( this.getSourceDirectory() ); 186 this.assertDirectoryExistence( this.getResourceDirectory() ); 187 this.assertDirectoryExistence( this.getBuildDirectory() ); 188 189 this.getProject().addCompileSourceRoot( 190 this.getSourceDirectory().getAbsolutePath() ); 191 192 final Resource resource = new Resource(); 193 resource.setDirectory( this.getResourceDirectory(). 194 getAbsolutePath() ); 195 196 resource.setFiltering( false ); 197 198 this.getProject().addResource( resource ); 199 200 final Module module = this.getModelManager(). 201 getModule( this.getModuleDescriptor() ); 202 203 if ( module != null ) 204 { 205 this.assertValidTemplates( module ); 206 if ( module.getImplementations() != null ) 207 { 208 this.generateBundles( module ); 209 } 210 } 211 } 212 catch ( final Exception e ) 213 { 214 throw new MojoExecutionException( e.getMessage(), e ); 215 } 216 } 217 218 private MessageFormat getMessage( final String key ) 219 { 220 if ( key == null ) 221 { 222 throw new NullPointerException( "key" ); 223 } 224 225 return new MessageFormat( 226 ResourceBundle.getBundle( JavaResourcesMojo.class.getName() ). 227 getString( key ) ); 228 229 } 230 231 private void assertDirectoryExistence( final File directory ) 232 throws MojoExecutionException 233 { 234 if ( !directory.exists() && !directory.mkdirs() ) 235 { 236 throw new MojoExecutionException( 237 this.getMessage( "cannotCreateDirectory" ). 238 format( new Object[] 239 { 240 directory.getAbsolutePath() 241 } ) ); 242 243 244 } 245 } 246 247 private void generateBundles( final Module module ) 248 throws Exception 249 { 250 InputStream in = null; 251 OutputStream out = null; 252 Writer writer = null; 253 254 try 255 { 256 final Properties bundleHashcodes = new Properties(); 257 final File propertiesFile = 258 new File( this.getBuildDirectory(), "bundles.properties" ); 259 260 if ( !propertiesFile.exists() && !propertiesFile.createNewFile() ) 261 { 262 final MessageFormat fmt = 263 this.getMessage( "cannotCreateFile" ); 264 265 throw new MojoExecutionException( fmt.format( new Object[] 266 { 267 propertiesFile.getAbsolutePath() 268 } ) ); 269 270 } 271 272 in = new FileInputStream( propertiesFile ); 273 bundleHashcodes.load( in ); 274 in.close(); 275 in = null; 276 277 for ( final Iterator it = module.getImplementations(). 278 getImplementation().iterator(); it.hasNext(); ) 279 { 280 final Implementation impl = (Implementation) it.next(); 281 if ( impl.getMessages() == null ) 282 { 283 continue; 284 } 285 286 final int bundleHash = 287 this.getModelManager().getHashCode( module, impl ); 288 289 final String propertyHash = 290 bundleHashcodes.getProperty( impl.getIdentifier() ); 291 292 if ( propertyHash == null || Integer.valueOf( propertyHash ). 293 intValue() != bundleHash ) 294 { 295 bundleHashcodes.setProperty( 296 impl.getIdentifier(), Integer.toString( bundleHash ) ); 297 298 final String bundlePath = 299 ( this.getModelManager().getJavaPackageName( impl ) 300 + '.' + this.getModelManager().getJavaTypeName( impl ) ). 301 replace( '.', File.separatorChar ); 302 303 final File bundleFile = new File( this.getSourceDirectory(), 304 bundlePath + ".java" ); 305 306 this.assertDirectoryExistence( bundleFile.getParentFile() ); 307 308 writer = 309 this.getEncoding() == null 310 ? new FileWriter( bundleFile ) 311 : new OutputStreamWriter( new FileOutputStream( 312 bundleFile ), this.getEncoding() ); 313 314 this.getLog().info( this.getMessage( "writingBundle" ). 315 format( new Object[] 316 { 317 bundleFile.getName() 318 } ) ); 319 320 this.getBundleGenerator(). 321 generateJava( module, impl, writer ); 322 323 writer.close(); 324 writer = null; 325 326 final Map bundleProperties = 327 this.getModelManager(). 328 getBundleProperties( module, impl ); 329 330 for ( final Iterator it2 = bundleProperties.entrySet(). 331 iterator(); it2.hasNext(); ) 332 { 333 final Map.Entry entry = (Map.Entry) it2.next(); 334 final String language = (String) entry.getKey(); 335 final Properties p = (Properties) entry.getValue(); 336 final File file = new File( this.getResourceDirectory(), 337 bundlePath + "_" + language 338 + ".properties" ); 339 340 this.getLog().info( this.getMessage( "writingBundle" ). 341 format( new Object[] 342 { 343 file.getName() 344 } ) ); 345 346 this.assertDirectoryExistence( file.getParentFile() ); 347 348 out = new FileOutputStream( file ); 349 p.store( out, this.getProject().getName() ); 350 out.close(); 351 out = null; 352 353 if ( this.getDefaultLanguage(). 354 equalsIgnoreCase( language ) ) 355 { 356 final File defaultFile = 357 new File( this.getResourceDirectory(), 358 bundlePath + ".properties" ); 359 360 this.assertDirectoryExistence( 361 defaultFile.getParentFile() ); 362 363 this.getLog().info( this. 364 getMessage( "writingBundle" ). 365 format( new Object[] 366 { 367 defaultFile.getName() 368 } ) ); 369 370 out = new FileOutputStream( defaultFile ); 371 p.store( out, this.getProject().getName() ); 372 out.close(); 373 out = null; 374 } 375 } 376 } 377 } 378 379 out = new FileOutputStream( propertiesFile ); 380 bundleHashcodes.store( out, this.getClass().getName() + ": " 381 + DateFormat.getDateTimeInstance(). 382 format( new Date() ) ); 383 384 out.close(); 385 out = null; 386 } 387 finally 388 { 389 try 390 { 391 if ( in != null ) 392 { 393 in.close(); 394 } 395 } 396 finally 397 { 398 try 399 { 400 if ( out != null ) 401 { 402 out.close(); 403 } 404 } 405 finally 406 { 407 if ( writer != null ) 408 { 409 writer.close(); 410 } 411 } 412 } 413 } 414 } 415 416 private void assertValidTemplates( final Module module ) 417 throws MojoExecutionException 418 { 419 if ( module.getImplementations() != null ) 420 { 421 for ( final Iterator it = module.getImplementations(). 422 getImplementation().iterator(); it.hasNext(); ) 423 { 424 final Implementation impl = (Implementation) it.next(); 425 if ( impl.getMessages() == null ) 426 { 427 continue; 428 } 429 430 for ( final Iterator m = impl.getMessages().getMessage(). 431 iterator(); m.hasNext(); ) 432 { 433 this.assertValidMessage( (Message) m.next() ); 434 } 435 } 436 } 437 438 if ( module.getMessages() != null ) 439 { 440 for ( final Iterator it = module.getMessages().getMessage(). 441 iterator(); it.hasNext(); ) 442 { 443 this.assertValidMessage( (Message) it.next() ); 444 } 445 } 446 } 447 448 private void assertValidMessage( final Message message ) 449 throws MojoExecutionException 450 { 451 if ( message.getTemplate() != null ) 452 { 453 for ( final Iterator it = message.getTemplate().getText(). 454 iterator(); it.hasNext(); ) 455 { 456 final Text text = (Text) it.next(); 457 try 458 { 459 new MessageFormat( text.getValue() ); 460 } 461 catch ( final IllegalArgumentException e ) 462 { 463 final MessageFormat fmt = 464 this.getMessage( "illegalTemplate" ); 465 466 throw new MojoExecutionException( fmt.format( new Object[] 467 { 468 text.getValue(), 469 message.getName(), 470 e.getMessage() 471 } ), e ); 472 473 } 474 } 475 } 476 } 477 478 //-------------------------------------------------------JavaResourcesMojo-- 479}