EMMA Coverage Report (generated Tue Feb 25 16:41:11 CET 2014)
[all classes][org.jomc.tools]

COVERAGE SUMMARY FOR SOURCE FILE [ResourceFileProcessor.java]

nameclass, %method, %block, %line, %
ResourceFileProcessor.java100% (1/1)100% (16/16)74%  (827/1112)85%  (163.6/192)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ResourceFileProcessor100% (1/1)100% (16/16)74%  (827/1112)85%  (163.6/192)
releaseAndClose (FileLock, FileChannel, Closeable, boolean): void 100% (1/1)7%   (15/225)18%  (4.4/24)
assertValidTemplates (Specification): void 100% (1/1)38%  (3/8)67%  (2/3)
getMessage (String, Object []): String 100% (1/1)72%  (13/18)67%  (2/3)
writeResourceBundleResourceFiles (Map, File, String): void 100% (1/1)77%  (175/226)84%  (29.4/35)
writePropertiesFile (Properties, String, File): void 100% (1/1)87%  (61/70)99%  (18.9/19)
assertValidTemplates (Implementation): void 100% (1/1)91%  (52/57)90%  (9/10)
ResourceFileProcessor (): void 100% (1/1)100% (3/3)100% (2/2)
ResourceFileProcessor (ResourceFileProcessor): void 100% (1/1)100% (8/8)100% (3/3)
getResourceBundleDefaultLocale (): Locale 100% (1/1)100% (26/26)100% (5/5)
getResourceBundleResources (Implementation): Map 100% (1/1)100% (120/120)100% (22/22)
getResourceBundleResources (Specification): Map 100% (1/1)100% (42/42)100% (8/8)
setResourceBundleDefaultLocale (Locale): void 100% (1/1)100% (4/4)100% (2/2)
writeResourceBundleResourceFiles (File): void 100% (1/1)100% (51/51)100% (8/8)
writeResourceBundleResourceFiles (Implementation, File): void 100% (1/1)100% (82/82)100% (17/17)
writeResourceBundleResourceFiles (Module, File): void 100% (1/1)100% (90/90)100% (14/14)
writeResourceBundleResourceFiles (Specification, File): void 100% (1/1)100% (82/82)100% (17/17)

1/*
2 *   Copyright (C) Christian Schulte, 2005-206
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 4670 2012-12-23 01:20:36Z schulte $
29 *
30 */
31package org.jomc.tools;
32 
33import java.io.ByteArrayOutputStream;
34import java.io.Closeable;
35import java.io.File;
36import java.io.IOException;
37import java.io.RandomAccessFile;
38import java.nio.ByteBuffer;
39import java.nio.channels.FileChannel;
40import java.nio.channels.FileLock;
41import java.text.MessageFormat;
42import java.util.HashMap;
43import java.util.Locale;
44import java.util.Map;
45import java.util.Properties;
46import java.util.ResourceBundle;
47import java.util.logging.Level;
48import org.apache.velocity.VelocityContext;
49import org.jomc.model.Implementation;
50import org.jomc.model.JavaTypeName;
51import org.jomc.model.Message;
52import org.jomc.model.Messages;
53import org.jomc.model.ModelObjectException;
54import org.jomc.model.Module;
55import org.jomc.model.Specification;
56import org.jomc.model.Text;
57 
58/**
59 * Processes resource files.
60 *
61 * <p><b>Use Cases:</b><br/><ul>
62 * <li>{@link #writeResourceBundleResourceFiles(File) }</li>
63 * <li>{@link #writeResourceBundleResourceFiles(Module, File) }</li>
64 * <li>{@link #writeResourceBundleResourceFiles(Specification, File) }</li>
65 * <li>{@link #writeResourceBundleResourceFiles(Implementation, File) }</li>
66 * </ul></p>
67 *
68 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
69 * @version $JOMC: ResourceFileProcessor.java 4670 2012-12-23 01:20:36Z schulte $
70 *
71 * @see #getModules()
72 */
73public class ResourceFileProcessor extends JomcTool
74{
75 
76    /** The language of the default language properties file of generated resource bundle resources. */
77    private Locale resourceBundleDefaultLocale;
78 
79    /** Creates a new {@code ResourceFileProcessor} instance. */
80    public ResourceFileProcessor()
81    {
82        super();
83    }
84 
85    /**
86     * Creates a new {@code ResourceFileProcessor} instance taking a {@code ResourceFileProcessor} instance to
87     * initialize the instance with.
88     *
89     * @param tool The instance to initialize the new instance with.
90     *
91     * @throws NullPointerException if {@code tool} is {@code null}.
92     * @throws IOException if copying {@code tool} fails.
93     */
94    public ResourceFileProcessor( final ResourceFileProcessor tool ) throws IOException
95    {
96        super( tool );
97        this.resourceBundleDefaultLocale = tool.resourceBundleDefaultLocale;
98    }
99 
100    /**
101     * Gets the language of the default language properties file of generated resource bundle resource files.
102     *
103     * @return The language of the default language properties file of generated resource bundle resource files.
104     *
105     * @see #setResourceBundleDefaultLocale(java.util.Locale)
106     */
107    public final Locale getResourceBundleDefaultLocale()
108    {
109        if ( this.resourceBundleDefaultLocale == null )
110        {
111            this.resourceBundleDefaultLocale = Locale.ENGLISH;
112 
113            if ( this.isLoggable( Level.CONFIG ) )
114            {
115                this.log( Level.CONFIG, getMessage( "defaultResourceBundleDefaultLocale",
116                                                    this.resourceBundleDefaultLocale ), null );
117 
118            }
119        }
120 
121        return this.resourceBundleDefaultLocale;
122    }
123 
124    /**
125     * Sets the language of the default language properties file of generated resource bundle resource files.
126     *
127     * @param value The language of the default language properties file of generated resource bundle resource files.
128     *
129     * @see #getResourceBundleDefaultLocale()
130     */
131    public final void setResourceBundleDefaultLocale( final Locale value )
132    {
133        this.resourceBundleDefaultLocale = value;
134    }
135 
136    /**
137     * Writes resource bundle resource files of the modules of the instance to a given directory.
138     *
139     * @param resourcesDirectory The directory to write resource bundle resource files to.
140     *
141     * @throws NullPointerException if {@code resourcesDirectory} is {@code null}.
142     * @throws IOException if writing resource bundle resource files fails.
143     * @throws ModelObjectException if compiling the name of a referenced type fails.
144     *
145     * @see #writeResourceBundleResourceFiles(org.jomc.model.Module, java.io.File)
146     */
147    public void writeResourceBundleResourceFiles( final File resourcesDirectory )
148        throws IOException, ModelObjectException
149    {
150        if ( resourcesDirectory == null )
151        {
152            throw new NullPointerException( "resourcesDirectory" );
153        }
154 
155        if ( this.getModules() != null )
156        {
157            for ( int i = 0, s0 = this.getModules().getModule().size(); i < s0; i++ )
158            {
159                this.writeResourceBundleResourceFiles( this.getModules().getModule().get( i ), resourcesDirectory );
160            }
161        }
162        else if ( this.isLoggable( Level.WARNING ) )
163        {
164            this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null );
165        }
166    }
167 
168    /**
169     * Writes resource bundle resource files of a given module from the modules of the instance to a given directory.
170     *
171     * @param module The module to process.
172     * @param resourcesDirectory The directory to write resource bundle resource files to.
173     *
174     * @throws NullPointerException if {@code module} or {@code resourcesDirectory} is {@code null}.
175     * @throws IOException if writing resource bundle resource files fails.
176     * @throws ModelObjectException if compiling the name of a referenced type fails.
177     *
178     * @see #writeResourceBundleResourceFiles(org.jomc.model.Specification, java.io.File)
179     * @see #writeResourceBundleResourceFiles(org.jomc.model.Implementation, java.io.File)
180     */
181    public void writeResourceBundleResourceFiles( final Module module, final File resourcesDirectory )
182        throws IOException, ModelObjectException
183    {
184        if ( module == null )
185        {
186            throw new NullPointerException( "module" );
187        }
188        if ( resourcesDirectory == null )
189        {
190            throw new NullPointerException( "resourcesDirectory" );
191        }
192 
193        if ( this.getModules() != null && this.getModules().getModule( module.getName() ) != null )
194        {
195            if ( module.getSpecifications() != null )
196            {
197                for ( int i = 0, s0 = module.getSpecifications().getSpecification().size(); i < s0; i++ )
198                {
199                    this.writeResourceBundleResourceFiles( module.getSpecifications().getSpecification().get( i ),
200                                                           resourcesDirectory );
201 
202                }
203            }
204 
205            if ( module.getImplementations() != null )
206            {
207                for ( int i = 0, s0 = module.getImplementations().getImplementation().size(); i < s0; i++ )
208                {
209                    this.writeResourceBundleResourceFiles( module.getImplementations().getImplementation().get( i ),
210                                                           resourcesDirectory );
211 
212                }
213            }
214        }
215        else if ( this.isLoggable( Level.WARNING ) )
216        {
217            this.log( Level.WARNING, getMessage( "moduleNotFound", module.getName() ), null );
218        }
219    }
220 
221    /**
222     * Writes resource bundle resource files of a given specification from the modules of the instance to a directory.
223     *
224     * @param specification The specification to process.
225     * @param resourcesDirectory The directory to write resource bundle resource files to.
226     *
227     * @throws NullPointerException if {@code specification} or {@code resourcesDirectory} is {@code null}.
228     * @throws IOException if writing resource bundle resource files fails.
229     * @throws ModelObjectException if compiling the name of the type referenced by the specification fails.
230     *
231     * @see #getResourceBundleResources(org.jomc.model.Specification)
232     */
233    public void writeResourceBundleResourceFiles( final Specification specification, final File resourcesDirectory )
234        throws IOException, ModelObjectException
235    {
236        if ( specification == null )
237        {
238            throw new NullPointerException( "implementation" );
239        }
240        if ( resourcesDirectory == null )
241        {
242            throw new NullPointerException( "resourcesDirectory" );
243        }
244 
245        if ( this.getModules() != null
246             && this.getModules().getSpecification( specification.getIdentifier() ) != null )
247        {
248            if ( specification.isClassDeclaration() )
249            {
250                if ( !resourcesDirectory.isDirectory() )
251                {
252                    throw new IOException( getMessage( "directoryNotFound", resourcesDirectory.getAbsolutePath() ) );
253                }
254 
255                this.assertValidTemplates( specification );
256 
257                final JavaTypeName javaTypeName = specification.getJavaTypeName();
258 
259                if ( javaTypeName != null )
260                {
261                    final String bundlePath = javaTypeName.getQualifiedName().replace( '.', File.separatorChar );
262                    this.writeResourceBundleResourceFiles(
263                        this.getResourceBundleResources( specification ), resourcesDirectory, bundlePath );
264 
265                }
266            }
267        }
268        else if ( this.isLoggable( Level.WARNING ) )
269        {
270            this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null );
271        }
272    }
273 
274    /**
275     * Writes resource bundle resource files of a given implementation from the modules of the instance to a directory.
276     *
277     * @param implementation The implementation to process.
278     * @param resourcesDirectory The directory to write resource bundle resource files to.
279     *
280     * @throws NullPointerException if {@code implementation} or {@code resourcesDirectory} is {@code null}.
281     * @throws IOException if writing resource bundle resource files fails.
282     * @throws ModelObjectException if compiling the name of the type referenced by the implementation fails.
283     *
284     * @see #getResourceBundleResources(org.jomc.model.Implementation)
285     */
286    public void writeResourceBundleResourceFiles( final Implementation implementation, final File resourcesDirectory )
287        throws IOException, ModelObjectException
288    {
289        if ( implementation == null )
290        {
291            throw new NullPointerException( "implementation" );
292        }
293        if ( resourcesDirectory == null )
294        {
295            throw new NullPointerException( "resourcesDirectory" );
296        }
297 
298        if ( this.getModules() != null
299             && this.getModules().getImplementation( implementation.getIdentifier() ) != null )
300        {
301            if ( implementation.isClassDeclaration() )
302            {
303                if ( !resourcesDirectory.isDirectory() )
304                {
305                    throw new IOException( getMessage( "directoryNotFound", resourcesDirectory.getAbsolutePath() ) );
306                }
307 
308                this.assertValidTemplates( implementation );
309 
310                final JavaTypeName javaTypeName = implementation.getJavaTypeName();
311 
312                if ( javaTypeName != null )
313                {
314                    final String bundlePath = javaTypeName.getQualifiedName().replace( '.', File.separatorChar );
315                    this.writeResourceBundleResourceFiles(
316                        this.getResourceBundleResources( implementation ), resourcesDirectory, bundlePath );
317 
318                }
319            }
320        }
321        else if ( this.isLoggable( Level.WARNING ) )
322        {
323            this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null );
324        }
325    }
326 
327    /**
328     * Gets resource bundle properties resources of a given specification.
329     *
330     * @param specification The specification to get resource bundle properties resources of.
331     *
332     * @return Resource bundle properties resources of {@code specification} or {@code null}, if no model objects are
333     * found.
334     *
335     * @throws NullPointerException if {@code specification} is {@code null}.
336     * @throws IOException if getting the resource bundle properties resources fails.
337     */
338    public Map<Locale, Properties> getResourceBundleResources( final Specification specification )
339        throws IOException
340    {
341        if ( specification == null )
342        {
343            throw new NullPointerException( "specification" );
344        }
345 
346        Map<Locale, Properties> properties = null;
347 
348        if ( this.getModules() != null
349             && this.getModules().getSpecification( specification.getIdentifier() ) != null )
350        {
351            properties = new HashMap<Locale, Properties>();
352        }
353        else if ( this.isLoggable( Level.WARNING ) )
354        {
355            this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null );
356        }
357 
358        return properties;
359    }
360 
361    /**
362     * Gets resource bundle properties resources of a given implementation.
363     *
364     * @param implementation The implementation to get resource bundle properties resources of.
365     *
366     * @return Resource bundle properties resources of {@code implementation} or {@code null}, if no model objects are
367     * found.
368     *
369     * @throws NullPointerException if {@code implementation} is {@code null}.
370     * @throws IOException if getting the resource bundle properties resources fails.
371     */
372    public Map<Locale, Properties> getResourceBundleResources( final Implementation implementation )
373        throws IOException
374    {
375        if ( implementation == null )
376        {
377            throw new NullPointerException( "implementation" );
378        }
379 
380        Map<Locale, Properties> properties = null;
381 
382        if ( this.getModules() != null
383             && this.getModules().getImplementation( implementation.getIdentifier() ) != null )
384        {
385            properties = new HashMap<Locale, java.util.Properties>( 10 );
386            final Messages messages = this.getModules().getMessages( implementation.getIdentifier() );
387 
388            if ( messages != null )
389            {
390                for ( int i = 0, s0 = messages.getMessage().size(); i < s0; i++ )
391                {
392                    final Message message = messages.getMessage().get( i );
393 
394                    if ( message.getTemplate() != null )
395                    {
396                        for ( int j = 0, s1 = message.getTemplate().getText().size(); j < s1; j++ )
397                        {
398                            final Text text = message.getTemplate().getText().get( j );
399                            final Locale locale = new Locale( text.getLanguage().toLowerCase() );
400                            Properties bundleProperties = properties.get( locale );
401 
402                            if ( bundleProperties == null )
403                            {
404                                bundleProperties = new Properties();
405                                properties.put( locale, bundleProperties );
406                            }
407 
408                            bundleProperties.setProperty( message.getName(), text.getValue() );
409                        }
410                    }
411                }
412            }
413        }
414        else if ( this.isLoggable( Level.WARNING ) )
415        {
416            this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null );
417        }
418 
419        return properties;
420    }
421 
422    private void writeResourceBundleResourceFiles( final Map<Locale, Properties> resources,
423                                                   final File resourcesDirectory, final String bundlePath )
424        throws IOException
425    {
426        if ( resources == null )
427        {
428            throw new NullPointerException( "resources" );
429        }
430        if ( resourcesDirectory == null )
431        {
432            throw new NullPointerException( "resourcesDirectory" );
433        }
434        if ( bundlePath == null )
435        {
436            throw new NullPointerException( "bundlePath" );
437        }
438 
439        Properties defProperties = null;
440        Properties fallbackProperties = null;
441 
442        final VelocityContext ctx = this.getVelocityContext();
443        final String toolName = ctx.get( "toolName" ).toString();
444        final String toolVersion = ctx.get( "toolVersion" ).toString();
445        final String toolUrl = ctx.get( "toolUrl" ).toString();
446 
447        for ( Map.Entry<Locale, Properties> e : resources.entrySet() )
448        {
449            final String language = e.getKey().getLanguage().toLowerCase();
450            final Properties p = e.getValue();
451            final File file = new File( resourcesDirectory, bundlePath + "_" + language + ".properties" );
452 
453            if ( this.getResourceBundleDefaultLocale().getLanguage().equalsIgnoreCase( language ) )
454            {
455                defProperties = p;
456            }
457 
458            fallbackProperties = p;
459 
460            if ( !file.getParentFile().exists() && !file.getParentFile().mkdirs() )
461            {
462                throw new IOException( getMessage( "failedCreatingDirectory",
463                                                   file.getParentFile().getAbsolutePath() ) );
464 
465            }
466 
467            if ( this.isLoggable( Level.INFO ) )
468            {
469                this.log( Level.INFO, getMessage( "writing", file.getCanonicalPath() ), null );
470            }
471 
472            this.writePropertiesFile( p, toolName + ' ' + toolVersion + " - See " + toolUrl, file );
473        }
474 
475        if ( defProperties == null )
476        {
477            defProperties = fallbackProperties;
478        }
479 
480        if ( defProperties != null )
481        {
482            final File file = new File( resourcesDirectory, bundlePath + ".properties" );
483 
484            if ( !file.getParentFile().exists() && !file.getParentFile().mkdirs() )
485            {
486                throw new IOException( getMessage( "failedCreatingDirectory",
487                                                   file.getParentFile().getAbsolutePath() ) );
488 
489            }
490 
491            if ( this.isLoggable( Level.INFO ) )
492            {
493                this.log( Level.INFO, getMessage( "writing", file.getCanonicalPath() ), null );
494            }
495 
496            this.writePropertiesFile( defProperties, toolName + ' ' + toolVersion + " - See " + toolUrl, file );
497        }
498    }
499 
500    private void assertValidTemplates( final Specification specification )
501    {
502        if ( specification == null )
503        {
504            throw new NullPointerException( "specification" );
505        }
506    }
507 
508    private void assertValidTemplates( final Implementation implementation )
509    {
510        if ( implementation == null )
511        {
512            throw new NullPointerException( "implementation" );
513        }
514 
515        final Messages messages = this.getModules().getMessages( implementation.getIdentifier() );
516 
517        if ( messages != null )
518        {
519            for ( int i = messages.getMessage().size() - 1; i >= 0; i-- )
520            {
521                final Message m = messages.getMessage().get( i );
522 
523                if ( m.getTemplate() != null )
524                {
525                    for ( int j = m.getTemplate().getText().size() - 1; j >= 0; j-- )
526                    {
527                        new MessageFormat( m.getTemplate().getText().get( j ).getValue() );
528                    }
529                }
530            }
531        }
532    }
533 
534    private void writePropertiesFile( final Properties properties, final String comments, final File propertiesFile )
535        throws IOException
536    {
537        RandomAccessFile randomAccessFile = null;
538        FileChannel fileChannel = null;
539        FileLock fileLock = null;
540        boolean suppressExceptionOnClose = true;
541 
542        final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
543        properties.store( byteStream, comments );
544        byteStream.close();
545 
546        final byte[] bytes = byteStream.toByteArray();
547 
548        try
549        {
550            randomAccessFile = new RandomAccessFile( propertiesFile, "rw" );
551            fileChannel = randomAccessFile.getChannel();
552            fileLock = fileChannel.lock();
553            fileChannel.truncate( bytes.length );
554            fileChannel.position( 0L );
555            fileChannel.write( ByteBuffer.wrap( bytes ) );
556            fileChannel.force( true );
557            suppressExceptionOnClose = false;
558        }
559        finally
560        {
561            this.releaseAndClose( fileLock, fileChannel, randomAccessFile, suppressExceptionOnClose );
562        }
563    }
564 
565    private void releaseAndClose( final FileLock fileLock, final FileChannel fileChannel,
566                                  final Closeable closeable, final boolean suppressExceptions )
567        throws IOException
568    {
569        try
570        {
571            if ( fileLock != null )
572            {
573                fileLock.release();
574            }
575        }
576        catch ( final IOException e )
577        {
578            if ( suppressExceptions )
579            {
580                this.log( Level.SEVERE, null, e );
581            }
582            else
583            {
584                throw e;
585            }
586        }
587        finally
588        {
589            try
590            {
591                if ( fileChannel != null )
592                {
593                    fileChannel.close();
594                }
595            }
596            catch ( final IOException e )
597            {
598                if ( suppressExceptions )
599                {
600                    this.log( Level.SEVERE, null, e );
601                }
602                else
603                {
604                    throw e;
605                }
606            }
607            finally
608            {
609                try
610                {
611                    if ( closeable != null )
612                    {
613                        closeable.close();
614                    }
615                }
616                catch ( final IOException e )
617                {
618                    if ( suppressExceptions )
619                    {
620                        this.log( Level.SEVERE, null, e );
621                    }
622                    else
623                    {
624                        throw e;
625                    }
626                }
627            }
628        }
629    }
630 
631    private static String getMessage( final String key, final Object... arguments )
632    {
633        if ( key == null )
634        {
635            throw new NullPointerException( "key" );
636        }
637 
638        return MessageFormat.format( ResourceBundle.getBundle(
639            ResourceFileProcessor.class.getName().replace( '.', '/' ) ).getString( key ), arguments );
640 
641    }
642 
643}

[all classes][org.jomc.tools]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov