View Javadoc
1   /*
2    *   Copyright (C) 2005 Christian Schulte <cs@schulte.it>
3    *   All rights reserved.
4    *
5    *   Redistribution and use in source and binary forms, with or without
6    *   modification, are permitted provided that the following conditions
7    *   are met:
8    *
9    *     o Redistributions of source code must retain the above copyright
10   *       notice, this list of conditions and the following disclaimer.
11   *
12   *     o Redistributions in binary form must reproduce the above copyright
13   *       notice, this list of conditions and the following disclaimer in
14   *       the documentation and/or other materials provided with the
15   *       distribution.
16   *
17   *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18   *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19   *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20   *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21   *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   *
28   *   $JOMC: ResourceFileProcessor.java 5307 2016-08-30 22:09:18Z schulte $
29   *
30   */
31  package org.jomc.tools;
32  
33  import java.io.Closeable;
34  import java.io.File;
35  import java.io.FileOutputStream;
36  import java.io.IOException;
37  import java.lang.reflect.UndeclaredThrowableException;
38  import java.nio.channels.FileLock;
39  import java.text.MessageFormat;
40  import java.util.HashMap;
41  import java.util.LinkedList;
42  import java.util.List;
43  import java.util.Locale;
44  import java.util.Map;
45  import java.util.Properties;
46  import java.util.ResourceBundle;
47  import java.util.concurrent.Callable;
48  import java.util.concurrent.CancellationException;
49  import java.util.concurrent.ExecutionException;
50  import java.util.concurrent.Future;
51  import java.util.logging.Level;
52  import org.apache.velocity.VelocityContext;
53  import org.jomc.model.Implementation;
54  import org.jomc.model.Implementations;
55  import org.jomc.model.JavaTypeName;
56  import org.jomc.model.Message;
57  import org.jomc.model.Messages;
58  import org.jomc.model.ModelObjectException;
59  import org.jomc.model.Module;
60  import org.jomc.model.Specification;
61  import org.jomc.model.Specifications;
62  import org.jomc.model.Text;
63  
64  /**
65   * Processes resource files.
66   *
67   * <p>
68   * <b>Use Cases:</b><br/><ul>
69   * <li>{@link #writeResourceBundleResourceFiles(File) }</li>
70   * <li>{@link #writeResourceBundleResourceFiles(Module, File) }</li>
71   * <li>{@link #writeResourceBundleResourceFiles(Specification, File) }</li>
72   * <li>{@link #writeResourceBundleResourceFiles(Implementation, File) }</li>
73   * </ul></p>
74   *
75   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
76   * @version $JOMC: ResourceFileProcessor.java 5307 2016-08-30 22:09:18Z schulte $
77   *
78   * @see #getModules()
79   */
80  public class ResourceFileProcessor extends JomcTool
81  {
82  
83      /**
84       * The language of the default language properties file of generated resource bundle resources.
85       */
86      private volatile Locale resourceBundleDefaultLocale;
87  
88      /**
89       * Creates a new {@code ResourceFileProcessor} instance.
90       */
91      public ResourceFileProcessor()
92      {
93          super();
94      }
95  
96      /**
97       * Creates a new {@code ResourceFileProcessor} instance taking a {@code ResourceFileProcessor} instance to
98       * initialize the instance with.
99       *
100      * @param tool The instance to initialize the new instance with.
101      *
102      * @throws NullPointerException if {@code tool} is {@code null}.
103      * @throws IOException if copying {@code tool} fails.
104      */
105     public ResourceFileProcessor( final ResourceFileProcessor tool ) throws IOException
106     {
107         super( tool );
108         this.resourceBundleDefaultLocale = tool.resourceBundleDefaultLocale;
109     }
110 
111     /**
112      * Gets the language of the default language properties file of generated resource bundle resource files.
113      *
114      * @return The language of the default language properties file of generated resource bundle resource files.
115      *
116      * @see #setResourceBundleDefaultLocale(java.util.Locale)
117      */
118     public final Locale getResourceBundleDefaultLocale()
119     {
120         if ( this.resourceBundleDefaultLocale == null )
121         {
122             this.resourceBundleDefaultLocale = Locale.ENGLISH;
123 
124             if ( this.isLoggable( Level.CONFIG ) )
125             {
126                 this.log( Level.CONFIG, getMessage( "defaultResourceBundleDefaultLocale",
127                                                     this.resourceBundleDefaultLocale ), null );
128 
129             }
130         }
131 
132         return this.resourceBundleDefaultLocale;
133     }
134 
135     /**
136      * Sets the language of the default language properties file of generated resource bundle resource files.
137      *
138      * @param value The language of the default language properties file of generated resource bundle resource files.
139      *
140      * @see #getResourceBundleDefaultLocale()
141      */
142     public final void setResourceBundleDefaultLocale( final Locale value )
143     {
144         this.resourceBundleDefaultLocale = value;
145     }
146 
147     /**
148      * Writes resource bundle resource files of the modules of the instance to a given directory.
149      *
150      * @param resourcesDirectory The directory to write resource bundle resource files to.
151      *
152      * @throws NullPointerException if {@code resourcesDirectory} is {@code null}.
153      * @throws IOException if writing resource bundle resource files fails.
154      * @throws ModelObjectException if compiling the name of a referenced type fails.
155      *
156      * @see #writeResourceBundleResourceFiles(org.jomc.model.Module, java.io.File)
157      */
158     public void writeResourceBundleResourceFiles( final File resourcesDirectory )
159         throws IOException, ModelObjectException
160     {
161         if ( resourcesDirectory == null )
162         {
163             throw new NullPointerException( "resourcesDirectory" );
164         }
165 
166         if ( this.getModules() != null )
167         {
168             this.writeResourceBundleResourceFiles( this.getModules().getSpecifications(),
169                                                    this.getModules().getImplementations(),
170                                                    resourcesDirectory );
171 
172         }
173         else if ( this.isLoggable( Level.WARNING ) )
174         {
175             this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null );
176         }
177     }
178 
179     /**
180      * Writes resource bundle resource files of a given module from the modules of the instance to a given directory.
181      *
182      * @param module The module to process.
183      * @param resourcesDirectory The directory to write resource bundle resource files to.
184      *
185      * @throws NullPointerException if {@code module} or {@code resourcesDirectory} is {@code null}.
186      * @throws IOException if writing resource bundle resource files fails.
187      * @throws ModelObjectException if compiling the name of a referenced type fails.
188      *
189      * @see #writeResourceBundleResourceFiles(org.jomc.model.Specification, java.io.File)
190      * @see #writeResourceBundleResourceFiles(org.jomc.model.Implementation, java.io.File)
191      */
192     public void writeResourceBundleResourceFiles( final Module module, final File resourcesDirectory )
193         throws IOException, ModelObjectException
194     {
195         if ( module == null )
196         {
197             throw new NullPointerException( "module" );
198         }
199         if ( resourcesDirectory == null )
200         {
201             throw new NullPointerException( "resourcesDirectory" );
202         }
203 
204         if ( this.getModules() != null && this.getModules().getModule( module.getName() ) != null )
205         {
206             this.writeResourceBundleResourceFiles( module.getSpecifications(), module.getImplementations(),
207                                                    resourcesDirectory );
208 
209         }
210         else if ( this.isLoggable( Level.WARNING ) )
211         {
212             this.log( Level.WARNING, getMessage( "moduleNotFound", module.getName() ), null );
213         }
214     }
215 
216     /**
217      * Writes resource bundle resource files of a given specification from the modules of the instance to a directory.
218      *
219      * @param specification The specification to process.
220      * @param resourcesDirectory The directory to write resource bundle resource files to.
221      *
222      * @throws NullPointerException if {@code specification} or {@code resourcesDirectory} is {@code null}.
223      * @throws IOException if writing resource bundle resource files fails.
224      * @throws ModelObjectException if compiling the name of the type referenced by the specification fails.
225      *
226      * @see #getResourceBundleResources(org.jomc.model.Specification)
227      */
228     public void writeResourceBundleResourceFiles( final Specification specification, final File resourcesDirectory )
229         throws IOException, ModelObjectException
230     {
231         if ( specification == null )
232         {
233             throw new NullPointerException( "implementation" );
234         }
235         if ( resourcesDirectory == null )
236         {
237             throw new NullPointerException( "resourcesDirectory" );
238         }
239 
240         if ( this.getModules() != null
241                  && this.getModules().getSpecification( specification.getIdentifier() ) != null )
242         {
243             if ( specification.isClassDeclaration() )
244             {
245                 if ( !resourcesDirectory.isDirectory() )
246                 {
247                     throw new IOException( getMessage( "directoryNotFound", resourcesDirectory.getAbsolutePath() ) );
248                 }
249 
250                 this.assertValidTemplates( specification );
251 
252                 final JavaTypeName javaTypeName = specification.getJavaTypeName();
253 
254                 if ( javaTypeName != null )
255                 {
256                     final String bundlePath = javaTypeName.getQualifiedName().replace( '.', File.separatorChar );
257                     this.writeResourceBundleResourceFiles(
258                         this.getResourceBundleResources( specification ), resourcesDirectory, bundlePath );
259 
260                 }
261             }
262         }
263         else if ( this.isLoggable( Level.WARNING ) )
264         {
265             this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null );
266         }
267     }
268 
269     /**
270      * Writes resource bundle resource files of a given implementation from the modules of the instance to a directory.
271      *
272      * @param implementation The implementation to process.
273      * @param resourcesDirectory The directory to write resource bundle resource files to.
274      *
275      * @throws NullPointerException if {@code implementation} or {@code resourcesDirectory} is {@code null}.
276      * @throws IOException if writing resource bundle resource files fails.
277      * @throws ModelObjectException if compiling the name of the type referenced by the implementation fails.
278      *
279      * @see #getResourceBundleResources(org.jomc.model.Implementation)
280      */
281     public void writeResourceBundleResourceFiles( final Implementation implementation, final File resourcesDirectory )
282         throws IOException, ModelObjectException
283     {
284         if ( implementation == null )
285         {
286             throw new NullPointerException( "implementation" );
287         }
288         if ( resourcesDirectory == null )
289         {
290             throw new NullPointerException( "resourcesDirectory" );
291         }
292 
293         if ( this.getModules() != null
294                  && this.getModules().getImplementation( implementation.getIdentifier() ) != null )
295         {
296             if ( implementation.isClassDeclaration() )
297             {
298                 if ( !resourcesDirectory.isDirectory() )
299                 {
300                     throw new IOException( getMessage( "directoryNotFound", resourcesDirectory.getAbsolutePath() ) );
301                 }
302 
303                 this.assertValidTemplates( implementation );
304 
305                 final JavaTypeName javaTypeName = implementation.getJavaTypeName();
306 
307                 if ( javaTypeName != null )
308                 {
309                     final String bundlePath = javaTypeName.getQualifiedName().replace( '.', File.separatorChar );
310                     this.writeResourceBundleResourceFiles(
311                         this.getResourceBundleResources( implementation ), resourcesDirectory, bundlePath );
312 
313                 }
314             }
315         }
316         else if ( this.isLoggable( Level.WARNING ) )
317         {
318             this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null );
319         }
320     }
321 
322     /**
323      * Gets resource bundle properties resources of a given specification.
324      *
325      * @param specification The specification to get resource bundle properties resources of.
326      *
327      * @return Resource bundle properties resources of {@code specification} or {@code null}, if no model objects are
328      * found.
329      *
330      * @throws NullPointerException if {@code specification} is {@code null}.
331      * @throws IOException if getting the resource bundle properties resources fails.
332      */
333     public Map<Locale, Properties> getResourceBundleResources( final Specification specification )
334         throws IOException
335     {
336         if ( specification == null )
337         {
338             throw new NullPointerException( "specification" );
339         }
340 
341         Map<Locale, Properties> properties = null;
342 
343         if ( this.getModules() != null
344                  && this.getModules().getSpecification( specification.getIdentifier() ) != null )
345         {
346             properties = new HashMap<Locale, Properties>();
347         }
348         else if ( this.isLoggable( Level.WARNING ) )
349         {
350             this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null );
351         }
352 
353         return properties;
354     }
355 
356     /**
357      * Gets resource bundle properties resources of a given implementation.
358      *
359      * @param implementation The implementation to get resource bundle properties resources of.
360      *
361      * @return Resource bundle properties resources of {@code implementation} or {@code null}, if no model objects are
362      * found.
363      *
364      * @throws NullPointerException if {@code implementation} is {@code null}.
365      * @throws IOException if getting the resource bundle properties resources fails.
366      */
367     public Map<Locale, Properties> getResourceBundleResources( final Implementation implementation )
368         throws IOException
369     {
370         if ( implementation == null )
371         {
372             throw new NullPointerException( "implementation" );
373         }
374 
375         Map<Locale, Properties> properties = null;
376 
377         if ( this.getModules() != null
378                  && this.getModules().getImplementation( implementation.getIdentifier() ) != null )
379         {
380             properties = new HashMap<Locale, java.util.Properties>( 10 );
381             final Messages messages = this.getModules().getMessages( implementation.getIdentifier() );
382 
383             if ( messages != null )
384             {
385                 for ( int i = 0, s0 = messages.getMessage().size(); i < s0; i++ )
386                 {
387                     final Message message = messages.getMessage().get( i );
388 
389                     if ( message.getTemplate() != null )
390                     {
391                         for ( int j = 0, s1 = message.getTemplate().getText().size(); j < s1; j++ )
392                         {
393                             final Text text = message.getTemplate().getText().get( j );
394                             final Locale locale = new Locale( text.getLanguage().toLowerCase() );
395                             Properties bundleProperties = properties.get( locale );
396 
397                             if ( bundleProperties == null )
398                             {
399                                 bundleProperties = new Properties();
400                                 properties.put( locale, bundleProperties );
401                             }
402 
403                             bundleProperties.setProperty( message.getName(), text.getValue() );
404                         }
405                     }
406                 }
407             }
408         }
409         else if ( this.isLoggable( Level.WARNING ) )
410         {
411             this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null );
412         }
413 
414         return properties;
415     }
416 
417     private void writeResourceBundleResourceFiles( final Specifications specifications,
418                                                    final Implementations implementations,
419                                                    final File resourcesDirectory )
420         throws IOException, ModelObjectException
421     {
422         try
423         {
424             class WriteResourceBundleResourceFilesTask implements Callable<Void>
425             {
426 
427                 final Specification specification;
428 
429                 final Implementation implementation;
430 
431                 WriteResourceBundleResourceFilesTask( final Specification specification,
432                                                       final Implementation implementation )
433                 {
434                     super();
435                     this.specification = specification;
436                     this.implementation = implementation;
437                 }
438 
439                 @Override
440                 public Void call() throws IOException, ModelObjectException
441                 {
442                     if ( this.specification != null )
443                     {
444                         writeResourceBundleResourceFiles( this.specification, resourcesDirectory );
445                     }
446                     if ( this.implementation != null )
447                     {
448                         writeResourceBundleResourceFiles( this.implementation, resourcesDirectory );
449                     }
450 
451                     return null;
452                 }
453 
454             }
455 
456             final List<WriteResourceBundleResourceFilesTask> tasks =
457                 new LinkedList<WriteResourceBundleResourceFilesTask>();
458 
459             if ( specifications != null )
460             {
461                 for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ )
462                 {
463                     final Specification specification = specifications.getSpecification().get( i );
464                     tasks.add( new WriteResourceBundleResourceFilesTask( specification, null ) );
465 
466                     if ( specification.isClassDeclaration() && specification.getJavaTypeName() != null )
467                     {
468                         if ( !resourcesDirectory.isDirectory() )
469                         {
470                             throw new IOException( getMessage( "directoryNotFound",
471                                                                resourcesDirectory.getAbsolutePath() ) );
472 
473                         }
474 
475                         final String bundlePath =
476                             specification.getJavaTypeName().getQualifiedName().replace( '.', File.separatorChar );
477 
478                         final File bundleDirectory = new File( resourcesDirectory, bundlePath ).getParentFile();
479 
480                         if ( !bundleDirectory.exists() && !bundleDirectory.mkdirs() )
481                         {
482                             throw new IOException( getMessage( "failedCreatingDirectory",
483                                                                bundleDirectory.getAbsolutePath() ) );
484 
485                         }
486                     }
487                 }
488             }
489 
490             if ( implementations != null )
491             {
492                 for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ )
493                 {
494                     final Implementation implementation = implementations.getImplementation().get( i );
495                     tasks.add( new WriteResourceBundleResourceFilesTask( null, implementation ) );
496 
497                     if ( implementation.isClassDeclaration() && implementation.getJavaTypeName() != null )
498                     {
499                         if ( !resourcesDirectory.isDirectory() )
500                         {
501                             throw new IOException( getMessage( "directoryNotFound",
502                                                                resourcesDirectory.getAbsolutePath() ) );
503 
504                         }
505 
506                         final String bundlePath =
507                             implementation.getJavaTypeName().getQualifiedName().replace( '.', File.separatorChar );
508 
509                         final File bundleDirectory = new File( resourcesDirectory, bundlePath ).getParentFile();
510 
511                         if ( !bundleDirectory.exists() && !bundleDirectory.mkdirs() )
512                         {
513                             throw new IOException( getMessage( "failedCreatingDirectory",
514                                                                bundleDirectory.getAbsolutePath() ) );
515 
516                         }
517                     }
518                 }
519             }
520 
521             if ( this.getExecutorService() != null && tasks.size() > 1 )
522             {
523                 for ( final Future<Void> task : this.getExecutorService().invokeAll( tasks ) )
524                 {
525                     task.get();
526                 }
527             }
528             else
529             {
530                 for ( int i = 0, s0 = tasks.size(); i < s0; i++ )
531                 {
532                     tasks.get( i ).call();
533                 }
534             }
535         }
536         catch ( final CancellationException e )
537         {
538             // JDK: As of JDK6 new IOException( getMessage( e.getCause() ), e.getCause() )
539             throw (IOException) new IOException( getMessage( e.getCause() ) ).initCause( e.getCause() );
540         }
541         catch ( final InterruptedException e )
542         {
543             // JDK: As of JDK6 new IOException( getMessage( e.getCause() ), e.getCause() )
544             throw (IOException) new IOException( getMessage( e.getCause() ) ).initCause( e.getCause() );
545         }
546         catch ( final ExecutionException e )
547         {
548             if ( e.getCause() instanceof ModelObjectException )
549             {
550                 throw (ModelObjectException) e.getCause();
551             }
552             else if ( e.getCause() instanceof IOException )
553             {
554                 throw (IOException) e.getCause();
555             }
556             else if ( e.getCause() instanceof RuntimeException )
557             {
558                 // The fork-join framework breaks the exception handling contract of Callable by re-throwing any
559                 // exception caught using a runtime exception.
560                 if ( e.getCause().getCause() instanceof ModelObjectException )
561                 {
562                     throw (ModelObjectException) e.getCause().getCause();
563                 }
564                 else if ( e.getCause().getCause() instanceof IOException )
565                 {
566                     throw (IOException) e.getCause().getCause();
567                 }
568                 else if ( e.getCause().getCause() instanceof RuntimeException )
569                 {
570                     throw (RuntimeException) e.getCause().getCause();
571                 }
572                 else if ( e.getCause().getCause() instanceof Error )
573                 {
574                     throw (Error) e.getCause().getCause();
575                 }
576                 else if ( e.getCause().getCause() instanceof Exception )
577                 {
578                     // Checked exception not declared to be thrown by the Callable's 'call' method.
579                     throw new UndeclaredThrowableException( e.getCause().getCause() );
580                 }
581                 else
582                 {
583                     throw (RuntimeException) e.getCause();
584                 }
585             }
586             else if ( e.getCause() instanceof Error )
587             {
588                 throw (Error) e.getCause();
589             }
590             else
591             {
592                 // Checked exception not declared to be thrown by the Callable's 'call' method.
593                 throw new UndeclaredThrowableException( e.getCause() );
594             }
595         }
596     }
597 
598     private void writeResourceBundleResourceFiles( final Map<Locale, Properties> resources,
599                                                    final File resourcesDirectory, final String bundlePath )
600         throws IOException
601     {
602         if ( resources == null )
603         {
604             throw new NullPointerException( "resources" );
605         }
606         if ( resourcesDirectory == null )
607         {
608             throw new NullPointerException( "resourcesDirectory" );
609         }
610         if ( bundlePath == null )
611         {
612             throw new NullPointerException( "bundlePath" );
613         }
614 
615         Properties defProperties = null;
616         Properties fallbackProperties = null;
617 
618         final VelocityContext ctx = this.getVelocityContext();
619         final String toolName = ctx.get( "toolName" ).toString();
620         final String toolVersion = ctx.get( "toolVersion" ).toString();
621         final String toolUrl = ctx.get( "toolUrl" ).toString();
622 
623         for ( final Map.Entry<Locale, Properties> e : resources.entrySet() )
624         {
625             final String language = e.getKey().getLanguage().toLowerCase();
626             final Properties p = e.getValue();
627             final File file = new File( resourcesDirectory, bundlePath + "_" + language + ".properties" );
628 
629             if ( this.getResourceBundleDefaultLocale().getLanguage().equalsIgnoreCase( language ) )
630             {
631                 defProperties = p;
632             }
633 
634             fallbackProperties = p;
635 
636             if ( !file.getParentFile().exists() && !file.getParentFile().mkdirs() )
637             {
638                 throw new IOException( getMessage( "failedCreatingDirectory",
639                                                    file.getParentFile().getAbsolutePath() ) );
640 
641             }
642 
643             if ( this.isLoggable( Level.INFO ) )
644             {
645                 this.log( Level.INFO, getMessage( "writing", file.getCanonicalPath() ), null );
646             }
647 
648             this.writePropertiesFile( p, toolName + ' ' + toolVersion + " - See " + toolUrl, file );
649         }
650 
651         if ( defProperties == null )
652         {
653             defProperties = fallbackProperties;
654         }
655 
656         if ( defProperties != null )
657         {
658             final File file = new File( resourcesDirectory, bundlePath + ".properties" );
659 
660             if ( !file.getParentFile().exists() && !file.getParentFile().mkdirs() )
661             {
662                 throw new IOException( getMessage( "failedCreatingDirectory",
663                                                    file.getParentFile().getAbsolutePath() ) );
664 
665             }
666 
667             if ( this.isLoggable( Level.INFO ) )
668             {
669                 this.log( Level.INFO, getMessage( "writing", file.getCanonicalPath() ), null );
670             }
671 
672             this.writePropertiesFile( defProperties, toolName + ' ' + toolVersion + " - See " + toolUrl, file );
673         }
674     }
675 
676     private void assertValidTemplates( final Specification specification )
677     {
678         if ( specification == null )
679         {
680             throw new NullPointerException( "specification" );
681         }
682     }
683 
684     private void assertValidTemplates( final Implementation implementation )
685     {
686         if ( implementation == null )
687         {
688             throw new NullPointerException( "implementation" );
689         }
690 
691         final Messages messages = this.getModules().getMessages( implementation.getIdentifier() );
692 
693         if ( messages != null )
694         {
695             for ( int i = messages.getMessage().size() - 1; i >= 0; i-- )
696             {
697                 final Message m = messages.getMessage().get( i );
698 
699                 if ( m.getTemplate() != null )
700                 {
701                     for ( int j = m.getTemplate().getText().size() - 1; j >= 0; j-- )
702                     {
703                         new MessageFormat( m.getTemplate().getText().get( j ).getValue() );
704                     }
705                 }
706             }
707         }
708     }
709 
710     private void writePropertiesFile( final Properties properties, final String comments, final File propertiesFile )
711         throws IOException
712     {
713         FileOutputStream out = null;
714         FileLock fileLock = null;
715 
716         try
717         {
718             out = new FileOutputStream( propertiesFile );
719             fileLock = out.getChannel().lock();
720 
721             properties.store( out, comments );
722             out.getChannel().force( true );
723 
724             fileLock.release();
725             fileLock = null;
726 
727             out.close();
728             out = null;
729         }
730         finally
731         {
732             this.releaseAndClose( fileLock, out );
733         }
734     }
735 
736     private void releaseAndClose( final FileLock fileLock, final Closeable closeable )
737         throws IOException
738     {
739         try
740         {
741             if ( fileLock != null )
742             {
743                 fileLock.release();
744             }
745         }
746         catch ( final IOException e )
747         {
748             this.log( Level.SEVERE, getMessage( e ), e );
749         }
750         finally
751         {
752             try
753             {
754                 if ( closeable != null )
755                 {
756                     closeable.close();
757                 }
758             }
759             catch ( final IOException e )
760             {
761                 this.log( Level.SEVERE, getMessage( e ), e );
762             }
763         }
764     }
765 
766     void initDefaults()
767     {
768         super.initDefaults();
769         this.getResourceBundleDefaultLocale();
770     }
771 
772     private static String getMessage( final Throwable t )
773     {
774         return t != null
775                    ? t.getMessage() != null && t.getMessage().trim().length() > 0
776                          ? t.getMessage()
777                          : getMessage( t.getCause() )
778                    : null;
779 
780     }
781 
782     private static String getMessage( final String key, final Object... arguments )
783     {
784         if ( key == null )
785         {
786             throw new NullPointerException( "key" );
787         }
788 
789         return MessageFormat.format( ResourceBundle.getBundle(
790             ResourceFileProcessor.class.getName().replace( '.', '/' ) ).getString( key ), arguments );
791 
792     }
793 
794 }