EMMA Coverage Report (generated Sun Jun 03 09:41:26 CEST 2012)
[all classes][org.jomc.tools]

COVERAGE SUMMARY FOR SOURCE FILE [ResourceFileProcessor.java]

nameclass, %method, %block, %line, %
ResourceFileProcessor.java100% (1/1)94%  (16/17)73%  (821/1120)84%  (159.6/189)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ResourceFileProcessor100% (1/1)94%  (16/17)73%  (821/1120)84%  (159.6/189)
getMessage (Throwable): String 0%   (0/1)0%   (0/14)0%   (0/1)
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% (79/79)100% (15/15)
writeResourceBundleResourceFiles (Module, File): void 100% (1/1)100% (90/90)100% (14/14)
writeResourceBundleResourceFiles (Specification, File): void 100% (1/1)100% (79/79)100% (15/15)

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

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