View Javadoc

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: SourceFileProcessor.java 4670 2012-12-23 01:20:36Z schulte $
29   *
30   */
31  package org.jomc.tools;
32  
33  import java.io.File;
34  import java.io.IOException;
35  import java.io.RandomAccessFile;
36  import java.io.StringWriter;
37  import java.nio.ByteBuffer;
38  import java.nio.channels.FileChannel;
39  import java.nio.channels.FileLock;
40  import java.text.MessageFormat;
41  import java.util.LinkedList;
42  import java.util.List;
43  import java.util.ResourceBundle;
44  import java.util.logging.Level;
45  import org.apache.commons.lang.StringUtils;
46  import org.apache.velocity.Template;
47  import org.apache.velocity.VelocityContext;
48  import org.apache.velocity.exception.VelocityException;
49  import org.jomc.model.Implementation;
50  import org.jomc.model.Implementations;
51  import org.jomc.model.Instance;
52  import org.jomc.model.Module;
53  import org.jomc.model.Specification;
54  import org.jomc.tools.model.SourceFileType;
55  import org.jomc.tools.model.SourceFilesType;
56  import org.jomc.tools.model.SourceSectionType;
57  import org.jomc.tools.model.SourceSectionsType;
58  import org.jomc.util.LineEditor;
59  import org.jomc.util.Section;
60  import org.jomc.util.SectionEditor;
61  import org.jomc.util.TrailingWhitespaceEditor;
62  
63  /**
64   * Processes source code files.
65   *
66   * <p><b>Use Cases:</b><br/><ul>
67   * <li>{@link #manageSourceFiles(File) }</li>
68   * <li>{@link #manageSourceFiles(Module, File) }</li>
69   * <li>{@link #manageSourceFiles(Specification, File) }</li>
70   * <li>{@link #manageSourceFiles(Implementation, File) }</li>
71   * </ul></p>
72   *
73   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
74   * @version $JOMC: SourceFileProcessor.java 4670 2012-12-23 01:20:36Z schulte $
75   */
76  public class SourceFileProcessor extends JomcTool
77  {
78  
79      /** The source file editor of the instance. */
80      private SourceFileProcessor.SourceFileEditor sourceFileEditor;
81  
82      /** Source files model. */
83      @Deprecated
84      private SourceFilesType sourceFilesType;
85  
86      /** Creates a new {@code SourceFileProcessor} instance. */
87      public SourceFileProcessor()
88      {
89          super();
90      }
91  
92      /**
93       * Creates a new {@code SourceFileProcessor} instance taking a {@code SourceFileProcessor} instance to initialize
94       * the instance with.
95       *
96       * @param tool The instance to initialize the new instance with,
97       *
98       * @throws NullPointerException if {@code tool} is {@code null}.
99       * @throws IOException if copying {@code tool} fails.
100      */
101     public SourceFileProcessor( final SourceFileProcessor tool ) throws IOException
102     {
103         super( tool );
104         this.sourceFilesType = tool.sourceFilesType != null ? tool.sourceFilesType.clone() : null;
105         this.sourceFileEditor = tool.sourceFileEditor;
106     }
107 
108     /**
109      * Gets the source files model of the instance.
110      * <p>This accessor method returns a reference to the live object, not a snapshot. Therefore any modification you
111      * make to the returned object will be present inside the object. This is why there is no {@code set} method.</p>
112      *
113      * @return The source files model of the instance.
114      *
115      * @see #getSourceFileType(org.jomc.model.Specification)
116      * @see #getSourceFileType(org.jomc.model.Implementation)
117      *
118      * @deprecated As of JOMC 1.2, please add source file models to {@code Specification}s and {@code Implementation}s
119      * directly. This method will be removed in version 2.0.
120      */
121     @Deprecated
122     public SourceFilesType getSourceFilesType()
123     {
124         if ( this.sourceFilesType == null )
125         {
126             this.sourceFilesType = new SourceFilesType();
127         }
128 
129         return this.sourceFilesType;
130     }
131 
132     /**
133      * Gets the model of a specification source file of the modules of the instance.
134      *
135      * @param specification The specification to get a source file model for.
136      *
137      * @return The source file model for {@code specification}. As of JOMC 1.2, this method returns {@code null} if no
138      * source file model is found.
139      *
140      * @throws NullPointerException if {@code specification} is {@code null}.
141      *
142      * @deprecated As of JOMC 1.2, please use method {@link #getSourceFilesType(org.jomc.model.Specification)}. This
143      * method will be removed in version 2.0.
144      */
145     @Deprecated
146     public SourceFileType getSourceFileType( final Specification specification )
147     {
148         if ( specification == null )
149         {
150             throw new NullPointerException( "specification" );
151         }
152 
153         SourceFileType sourceFileType = null;
154 
155         if ( this.getModules() != null
156              && this.getModules().getSpecification( specification.getIdentifier() ) != null )
157         {
158             sourceFileType = this.getSourceFilesType().getSourceFile( specification.getIdentifier() );
159 
160             if ( sourceFileType == null )
161             {
162                 sourceFileType = specification.getAnyObject( SourceFileType.class );
163             }
164         }
165         else if ( this.isLoggable( Level.WARNING ) )
166         {
167             this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null );
168         }
169 
170         return sourceFileType;
171     }
172 
173     /**
174      * Gets the source files model of a specification of the modules of the instance.
175      *
176      * @param specification The specification to get a source files model for.
177      *
178      * @return The source files model for {@code specification} or {@code null}, if no source files model is found.
179      *
180      * @throws NullPointerException if {@code specification} is {@code null}.
181      *
182      * @since 1.2
183      */
184     public SourceFilesType getSourceFilesType( final Specification specification )
185     {
186         if ( specification == null )
187         {
188             throw new NullPointerException( "specification" );
189         }
190 
191         SourceFilesType model = null;
192 
193         if ( this.getModules() != null
194              && this.getModules().getSpecification( specification.getIdentifier() ) != null )
195         {
196             final SourceFileType sourceFileType = this.getSourceFileType( specification );
197 
198             if ( sourceFileType != null )
199             {
200                 model = new SourceFilesType();
201                 model.getSourceFile().add( sourceFileType );
202             }
203             else
204             {
205                 model = specification.getAnyObject( SourceFilesType.class );
206             }
207         }
208         else if ( this.isLoggable( Level.WARNING ) )
209         {
210             this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null );
211         }
212 
213         return model;
214     }
215 
216     /**
217      * Gets the model of an implementation source file of the modules of the instance.
218      *
219      * @param implementation The implementation to get a source file model for.
220      *
221      * @return The source file model for {@code implementation}. As of JOMC 1.2, this method returns {@code null} if no
222      * source file model is found.
223      *
224      * @throws NullPointerException if {@code implementation} is {@code null}.
225      *
226      * @deprecated As of JOMC 1.2, please use method {@link #getSourceFilesType(org.jomc.model.Implementation)}. This
227      * method will be removed in version 2.0.
228      */
229     @Deprecated
230     public SourceFileType getSourceFileType( final Implementation implementation )
231     {
232         if ( implementation == null )
233         {
234             throw new NullPointerException( "implementation" );
235         }
236 
237         SourceFileType sourceFileType = null;
238 
239         if ( this.getModules() != null
240              && this.getModules().getImplementation( implementation.getIdentifier() ) != null )
241         {
242             sourceFileType = this.getSourceFilesType().getSourceFile( implementation.getIdentifier() );
243 
244             if ( sourceFileType == null )
245             {
246                 sourceFileType = implementation.getAnyObject( SourceFileType.class );
247             }
248         }
249         else if ( this.isLoggable( Level.WARNING ) )
250         {
251             this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null );
252         }
253 
254         return sourceFileType;
255     }
256 
257     /**
258      * Gets the source files model of an implementation of the modules of the instance.
259      *
260      * @param implementation The implementation to get a source files model for.
261      *
262      * @return The source files model for {@code implementation} or {@code null}, if no source files model is found.
263      *
264      * @throws NullPointerException if {@code implementation} is {@code null}.
265      *
266      * @since 1.2
267      */
268     public SourceFilesType getSourceFilesType( final Implementation implementation )
269     {
270         if ( implementation == null )
271         {
272             throw new NullPointerException( "implementation" );
273         }
274 
275         SourceFilesType model = null;
276 
277         if ( this.getModules() != null
278              && this.getModules().getImplementation( implementation.getIdentifier() ) != null )
279         {
280             final SourceFileType sourceFileType = this.getSourceFileType( implementation );
281 
282             if ( sourceFileType != null )
283             {
284                 model = new SourceFilesType();
285                 model.getSourceFile().add( sourceFileType );
286             }
287             else
288             {
289                 final Instance instance = this.getModules().getInstance( implementation.getIdentifier() );
290                 assert instance != null : "Instance '" + implementation.getIdentifier() + "' not found.";
291                 model = instance.getAnyObject( SourceFilesType.class );
292             }
293         }
294         else if ( this.isLoggable( Level.WARNING ) )
295         {
296             this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null );
297         }
298 
299         return model;
300     }
301 
302     /**
303      * Gets the source file editor of the instance.
304      *
305      * @return The source file editor of the instance.
306      *
307      * @since 1.2
308      *
309      * @see #setSourceFileEditor(org.jomc.tools.SourceFileProcessor.SourceFileEditor)
310      */
311     public final SourceFileProcessor.SourceFileEditor getSourceFileEditor()
312     {
313         if ( this.sourceFileEditor == null )
314         {
315             this.sourceFileEditor =
316                 new SourceFileProcessor.SourceFileEditor( new TrailingWhitespaceEditor( this.getLineSeparator() ),
317                                                           this.getLineSeparator() );
318 
319         }
320 
321         return this.sourceFileEditor;
322     }
323 
324     /**
325      * Sets the source file editor of the instance.
326      *
327      * @param value The new source file editor of the instance or {@code null}.
328      *
329      * @since 1.2
330      *
331      * @see #getSourceFileEditor()
332      */
333     public final void setSourceFileEditor( final SourceFileProcessor.SourceFileEditor value )
334     {
335         this.sourceFileEditor = value;
336     }
337 
338     /**
339      * Gets a new editor for editing the source file of a given specification of the modules of the instance.
340      *
341      * @param specification The specification whose source file to edit.
342      *
343      * @return A new editor for editing the source file of {@code specification}.
344      *
345      * @throws NullPointerException if {@code specification} is {@code null}.
346      *
347      * @deprecated As of JOMC 1.2, please use method {@link #getSourceFileEditor()}. This method will be removed in
348      * version 2.0.
349      *
350      * @see SourceFileEditor#edit(org.jomc.model.Specification, org.jomc.tools.model.SourceFileType, java.io.File)
351      */
352     @Deprecated
353     public SourceFileProcessor.SourceFileEditor getSourceFileEditor( final Specification specification )
354     {
355         if ( specification == null )
356         {
357             throw new NullPointerException( "specification" );
358         }
359 
360         return this.getSourceFileEditor();
361     }
362 
363     /**
364      * Gets a new editor for editing the source file of a given implementation of the modules of the instance.
365      *
366      * @param implementation The implementation whose source file to edit.
367      *
368      * @return A new editor for editing the source file of {@code implementation}.
369      *
370      * @throws NullPointerException if {@code implementation} is {@code null}.
371      *
372      * @deprecated As of JOMC 1.2, please use method {@link #getSourceFileEditor()}. This method will be removed in
373      * version 2.0.
374      *
375      * @see SourceFileEditor#edit(org.jomc.model.Implementation, org.jomc.tools.model.SourceFileType, java.io.File)
376      */
377     @Deprecated
378     public SourceFileProcessor.SourceFileEditor getSourceFileEditor( final Implementation implementation )
379     {
380         if ( implementation == null )
381         {
382             throw new NullPointerException( "implementation" );
383         }
384 
385         return this.getSourceFileEditor();
386     }
387 
388     /**
389      * Manages the source files of the modules of the instance.
390      *
391      * @param sourcesDirectory The directory holding the source files to manage.
392      *
393      * @throws NullPointerException if {@code sourcesDirectory} is {@code null}.
394      * @throws IOException if managing source files fails.
395      *
396      * @see #manageSourceFiles(org.jomc.model.Module, java.io.File)
397      */
398     public void manageSourceFiles( final File sourcesDirectory ) throws IOException
399     {
400         if ( sourcesDirectory == null )
401         {
402             throw new NullPointerException( "sourcesDirectory" );
403         }
404 
405         if ( this.getModules() != null )
406         {
407             for ( int i = this.getModules().getModule().size() - 1; i >= 0; i-- )
408             {
409                 this.manageSourceFiles( this.getModules().getModule().get( i ), sourcesDirectory );
410             }
411         }
412         else if ( this.isLoggable( Level.WARNING ) )
413         {
414             this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null );
415         }
416     }
417 
418     /**
419      * Manages the source files of a given module of the modules of the instance.
420      *
421      * @param module The module to process.
422      * @param sourcesDirectory The directory holding the source files to manage.
423      *
424      * @throws NullPointerException if {@code module} or {@code sourcesDirectory} is {@code null}.
425      * @throws IOException if managing source files fails.
426      *
427      * @see #manageSourceFiles(org.jomc.model.Specification, java.io.File)
428      * @see #manageSourceFiles(org.jomc.model.Implementation, java.io.File)
429      */
430     public void manageSourceFiles( final Module module, final File sourcesDirectory ) throws IOException
431     {
432         if ( module == null )
433         {
434             throw new NullPointerException( "module" );
435         }
436         if ( sourcesDirectory == null )
437         {
438             throw new NullPointerException( "sourcesDirectory" );
439         }
440 
441         if ( this.getModules() != null && this.getModules().getModule( module.getName() ) != null )
442         {
443             if ( module.getSpecifications() != null )
444             {
445                 for ( int i = 0, s0 = module.getSpecifications().getSpecification().size(); i < s0; i++ )
446                 {
447                     this.manageSourceFiles( module.getSpecifications().getSpecification().get( i ), sourcesDirectory );
448                 }
449             }
450             if ( module.getImplementations() != null )
451             {
452                 for ( int i = 0, s0 = module.getImplementations().getImplementation().size(); i < s0; i++ )
453                 {
454                     this.manageSourceFiles( module.getImplementations().getImplementation().get( i ), sourcesDirectory );
455                 }
456             }
457         }
458         else if ( this.isLoggable( Level.WARNING ) )
459         {
460             this.log( Level.WARNING, getMessage( "moduleNotFound", module.getName() ), null );
461         }
462     }
463 
464     /**
465      * Manages the source files of a given specification of the modules of the instance.
466      *
467      * @param specification The specification to process.
468      * @param sourcesDirectory The directory holding the source files to manage.
469      *
470      * @throws NullPointerException if {@code specification} or {@code sourcesDirectory} is {@code null}.
471      * @throws IOException if managing source files fails.
472      *
473      * @see #getSourceFileEditor()
474      * @see #getSourceFilesType(org.jomc.model.Specification)
475      */
476     public void manageSourceFiles( final Specification specification, final File sourcesDirectory ) throws IOException
477     {
478         if ( specification == null )
479         {
480             throw new NullPointerException( "specification" );
481         }
482         if ( sourcesDirectory == null )
483         {
484             throw new NullPointerException( "sourcesDirectory" );
485         }
486 
487         if ( this.getModules() != null
488              && this.getModules().getSpecification( specification.getIdentifier() ) != null )
489         {
490             if ( specification.isClassDeclaration() )
491             {
492                 boolean manage = true;
493                 final Implementations implementations = this.getModules().getImplementations();
494 
495                 if ( implementations != null )
496                 {
497                     for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ )
498                     {
499                         final Implementation impl = implementations.getImplementation().get( i );
500 
501                         if ( impl.isClassDeclaration() && specification.getClazz().equals( impl.getClazz() ) )
502                         {
503                             this.manageSourceFiles( impl, sourcesDirectory );
504                             manage = false;
505                             break;
506                         }
507                     }
508                 }
509 
510                 if ( manage )
511                 {
512                     final SourceFilesType model = this.getSourceFilesType( specification );
513 
514                     if ( model != null )
515                     {
516                         for ( int i = 0, s0 = model.getSourceFile().size(); i < s0; i++ )
517                         {
518                             this.getSourceFileEditor().edit(
519                                 specification, model.getSourceFile().get( i ), sourcesDirectory );
520 
521                         }
522                     }
523                 }
524             }
525         }
526         else if ( this.isLoggable( Level.WARNING ) )
527         {
528             this.log( Level.WARNING, getMessage( "specificationNotFound", specification.getIdentifier() ), null );
529         }
530     }
531 
532     /**
533      * Manages the source files of a given implementation of the modules of the instance.
534      *
535      * @param implementation The implementation to process.
536      * @param sourcesDirectory The directory holding the source files to manage.
537      *
538      * @throws NullPointerException if {@code implementation} or {@code sourcesDirectory} is {@code null}.
539      * @throws IOException if managing source files fails.
540      *
541      * @see #getSourceFileEditor()
542      * @see #getSourceFilesType(org.jomc.model.Implementation)
543      */
544     public void manageSourceFiles( final Implementation implementation, final File sourcesDirectory )
545         throws IOException
546     {
547         if ( implementation == null )
548         {
549             throw new NullPointerException( "implementation" );
550         }
551         if ( sourcesDirectory == null )
552         {
553             throw new NullPointerException( "sourcesDirectory" );
554         }
555 
556         if ( this.getModules() != null
557              && this.getModules().getImplementation( implementation.getIdentifier() ) != null )
558         {
559             if ( implementation.isClassDeclaration() )
560             {
561                 final SourceFilesType model = this.getSourceFilesType( implementation );
562 
563                 if ( model != null )
564                 {
565                     for ( int i = 0, s0 = model.getSourceFile().size(); i < s0; i++ )
566                     {
567                         this.getSourceFileEditor().edit(
568                             implementation, model.getSourceFile().get( i ), sourcesDirectory );
569 
570                     }
571                 }
572             }
573         }
574         else if ( this.isLoggable( Level.WARNING ) )
575         {
576             this.log( Level.WARNING, getMessage( "implementationNotFound", implementation.getIdentifier() ), null );
577         }
578     }
579 
580     private static String getMessage( final String key, final Object... arguments )
581     {
582         if ( key == null )
583         {
584             throw new NullPointerException( "key" );
585         }
586 
587         return MessageFormat.format( ResourceBundle.getBundle(
588             SourceFileProcessor.class.getName().replace( '.', '/' ) ).getString( key ), arguments );
589 
590     }
591 
592     private static String getMessage( final Throwable t )
593     {
594         return t != null ? t.getMessage() != null ? t.getMessage() : getMessage( t.getCause() ) : null;
595     }
596 
597     /**
598      * Extension to {@code SectionEditor} adding support for editing source code files.
599      *
600      * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
601      * @version $JOMC: SourceFileProcessor.java 4670 2012-12-23 01:20:36Z schulte $
602      *
603      * @see #edit(org.jomc.model.Specification, org.jomc.tools.model.SourceFileType, java.io.File)
604      * @see #edit(org.jomc.model.Implementation, org.jomc.tools.model.SourceFileType, java.io.File)
605      */
606     public class SourceFileEditor extends SectionEditor
607     {
608 
609         /** {@code Specification} of the instance or {@code null}. */
610         private Specification specification;
611 
612         /** {@code Implementation} of the instance or {@code null}. */
613         private Implementation implementation;
614 
615         /** The source code file to edit. */
616         private SourceFileType sourceFileType;
617 
618         /** The {@code VelocityContext} of the instance. */
619         private VelocityContext velocityContext;
620 
621         /** List of sections added to the input. */
622         @Deprecated
623         private List<Section> addedSections;
624 
625         /** List of sections without corresponding model entry. */
626         @Deprecated
627         private List<Section> unknownSections;
628 
629         /**
630          * Creates a new {@code SourceFileEditor} instance.
631          *
632          * @since 1.2
633          */
634         public SourceFileEditor()
635         {
636             this( (LineEditor) null, (String) null );
637         }
638 
639         /**
640          * Creates a new {@code SourceFileEditor} instance taking a string to use for separating lines.
641          *
642          * @param lineSeparator String to use for separating lines.
643          *
644          * @since 1.2
645          */
646         public SourceFileEditor( final String lineSeparator )
647         {
648             this( (LineEditor) null, lineSeparator );
649         }
650 
651         /**
652          * Creates a new {@code SourceFileEditor} instance taking an editor to chain.
653          *
654          * @param editor The editor to chain.
655          *
656          * @since 1.2
657          */
658         public SourceFileEditor( final LineEditor editor )
659         {
660             this( editor, null );
661         }
662 
663         /**
664          * Creates a new {@code SourceFileEditor} instance taking an editor to chain and a string to use for separating
665          * lines.
666          *
667          * @param editor The editor to chain.
668          * @param lineSeparator String to use for separating lines.
669          *
670          * @since 1.2
671          */
672         public SourceFileEditor( final LineEditor editor, final String lineSeparator )
673         {
674             super( editor, lineSeparator );
675         }
676 
677         /**
678          * Creates a new {@code SourceFileEditor} taking a {@code Specification} to edit source code of.
679          *
680          * @param specification The specification to edit source code of.
681          *
682          * @deprecated As of JOMC 1.2, please use method {@link #edit(org.jomc.model.Specification, org.jomc.tools.model.SourceFileType, java.io.File)}.
683          * This constructor will be removed in version 2.0.
684          */
685         @Deprecated
686         public SourceFileEditor( final Specification specification )
687         {
688             this( specification, null, null );
689         }
690 
691         /**
692          * Creates a new {@code SourceFileEditor} taking a {@code Specification} to edit source code of and a line
693          * separator.
694          *
695          * @param specification The specification to edit source code of.
696          * @param lineSeparator The line separator of the editor.
697          *
698          * @deprecated As of JOMC 1.2, please use method {@link #edit(org.jomc.model.Specification, org.jomc.tools.model.SourceFileType, java.io.File)}.
699          * This constructor will be removed in version 2.0.
700          */
701         @Deprecated
702         public SourceFileEditor( final Specification specification, final String lineSeparator )
703         {
704             this( specification, null, lineSeparator );
705         }
706 
707         /**
708          * Creates a new {@code SourceFileEditor} taking a {@code Specification} to edit source code of and an editor to
709          * chain.
710          *
711          * @param specification The specification backing the editor.
712          * @param lineEditor The editor to chain.
713          *
714          * @deprecated As of JOMC 1.2, please use method {@link #edit(org.jomc.model.Specification, org.jomc.tools.model.SourceFileType, java.io.File)}.
715          * This constructor will be removed in version 2.0.
716          */
717         @Deprecated
718         public SourceFileEditor( final Specification specification, final LineEditor lineEditor )
719         {
720             this( specification, lineEditor, null );
721         }
722 
723         /**
724          * Creates a new {@code SourceFileEditor} taking a {@code Specification} to edit source code of, an editor to
725          * chain and a line separator.
726          *
727          * @param specification The specification backing the editor.
728          * @param lineEditor The editor to chain.
729          * @param lineSeparator The line separator of the editor.
730          *
731          * @deprecated As of JOMC 1.2, please use method {@link #edit(org.jomc.model.Specification, org.jomc.tools.model.SourceFileType, java.io.File)}.
732          * This constructor will be removed in version 2.0.
733          */
734         @Deprecated
735         public SourceFileEditor( final Specification specification, final LineEditor lineEditor,
736                                  final String lineSeparator )
737         {
738             super( lineEditor, lineSeparator );
739             this.specification = specification;
740             this.implementation = null;
741 
742             assert getModules().getSpecification( specification.getIdentifier() ) != null :
743                 "Specification '" + specification.getIdentifier() + "' not found.";
744 
745         }
746 
747         /**
748          * Creates a new {@code SourceFileEditor} taking an {@code Implementation} to edit source code of.
749          *
750          * @param implementation The implementation to edit source code of.
751          *
752          * @deprecated As of JOMC 1.2, please use method {@link #edit(org.jomc.model.Implementation, org.jomc.tools.model.SourceFileType, java.io.File)}.
753          * This constructor will be removed in version 2.0.
754          */
755         @Deprecated
756         public SourceFileEditor( final Implementation implementation )
757         {
758             this( implementation, null, null );
759         }
760 
761         /**
762          * Creates a new {@code SourceFileEditor} taking an {@code Implementation} to edit source code of and a line
763          * separator.
764          *
765          * @param implementation The implementation to edit source code of.
766          * @param lineSeparator The line separator of the editor.
767          *
768          * @deprecated As of JOMC 1.2, please use method {@link #edit(org.jomc.model.Implementation, org.jomc.tools.model.SourceFileType, java.io.File)}.
769          * This constructor will be removed in version 2.0.
770          */
771         @Deprecated
772         public SourceFileEditor( final Implementation implementation, final String lineSeparator )
773         {
774             this( implementation, null, lineSeparator );
775         }
776 
777         /**
778          * Creates a new {@code SourceFileEditor} taking an {@code Implementation} to edit source code of and an editor
779          * to chain.
780          *
781          * @param implementation The implementation to edit source code of.
782          * @param lineEditor The editor to chain.
783          *
784          * @deprecated As of JOMC 1.2, please use method {@link #edit(org.jomc.model.Implementation, org.jomc.tools.model.SourceFileType, java.io.File)}.
785          * This constructor will be removed in version 2.0.
786          */
787         @Deprecated
788         public SourceFileEditor( final Implementation implementation, final LineEditor lineEditor )
789         {
790             this( implementation, lineEditor, null );
791         }
792 
793         /**
794          * Creates a new {@code SourceFileEditor} taking an {@code Implementation} to edit source code of, an editor
795          * to chain and a line separator.
796          *
797          * @param implementation The implementation to edit source code of.
798          * @param lineEditor The editor to chain.
799          * @param lineSeparator The line separator of the editor.
800          *
801          * @deprecated As of JOMC 1.2, please use method {@link #edit(org.jomc.model.Implementation, org.jomc.tools.model.SourceFileType, java.io.File)}.
802          * This constructor will be removed in version 2.0.
803          */
804         @Deprecated
805         public SourceFileEditor( final Implementation implementation, final LineEditor lineEditor,
806                                  final String lineSeparator )
807         {
808             super( lineEditor, lineSeparator );
809             this.implementation = implementation;
810             this.specification = null;
811 
812             assert getModules().getImplementation( implementation.getIdentifier() ) != null :
813                 "Implementation '" + implementation.getIdentifier() + "' not found.";
814 
815         }
816 
817         /**
818          * Edits a source file of a given specification.
819          *
820          * @param specification The specification to edit a source file of.
821          * @param sourceFileType The model of the source file to edit.
822          * @param sourcesDirectory The directory holding the source file to edit.
823          *
824          * @throws NullPointerException if {@code specification}, {@code sourceFileType} or {@code sourcesDirectory} is
825          * {@code null}.
826          * @throws IOException if editing fails.
827          *
828          * @since 1.2
829          */
830         public final void edit( final Specification specification, final SourceFileType sourceFileType,
831                                 final File sourcesDirectory ) throws IOException
832         {
833             if ( specification == null )
834             {
835                 throw new NullPointerException( "specification" );
836             }
837             if ( sourceFileType == null )
838             {
839                 throw new NullPointerException( "sourceFileType" );
840             }
841             if ( sourcesDirectory == null )
842             {
843                 throw new NullPointerException( "sourcesDirectory" );
844             }
845 
846             try
847             {
848                 if ( getModules() != null
849                      && getModules().getSpecification( specification.getIdentifier() ) != null )
850                 {
851                     this.specification = specification;
852                     this.sourceFileType = sourceFileType;
853                     this.velocityContext = SourceFileProcessor.this.getVelocityContext();
854                     this.velocityContext.put( "specification", specification );
855                     this.velocityContext.put( "smodel", sourceFileType );
856 
857                     this.editSourceFile( sourcesDirectory );
858                 }
859                 else
860                 {
861                     throw new IOException( getMessage( "specificationNotFound", specification.getIdentifier() ) );
862                 }
863             }
864             finally
865             {
866                 this.specification = null;
867                 this.implementation = null;
868                 this.sourceFileType = null;
869                 this.velocityContext = null;
870             }
871         }
872 
873         /**
874          * Edits a source file of a given implementation.
875          *
876          * @param implementation The implementation to edit a source file of.
877          * @param sourceFileType The model of the source file to edit.
878          * @param sourcesDirectory The directory holding the source file to edit.
879          *
880          * @throws NullPointerException if {@code implementation}, {@code sourceFileType} or {@code sourcesDirectory} is
881          * {@code null}.
882          * @throws IOException if editing fails.
883          *
884          * @since 1.2
885          */
886         public final void edit( final Implementation implementation, final SourceFileType sourceFileType,
887                                 final File sourcesDirectory ) throws IOException
888         {
889             if ( implementation == null )
890             {
891                 throw new NullPointerException( "implementation" );
892             }
893             if ( sourceFileType == null )
894             {
895                 throw new NullPointerException( "sourceFileType" );
896             }
897             if ( sourcesDirectory == null )
898             {
899                 throw new NullPointerException( "sourcesDirectory" );
900             }
901 
902             try
903             {
904                 if ( getModules() != null
905                      && getModules().getImplementation( implementation.getIdentifier() ) != null )
906                 {
907                     this.implementation = implementation;
908                     this.sourceFileType = sourceFileType;
909                     this.velocityContext = SourceFileProcessor.this.getVelocityContext();
910                     this.velocityContext.put( "implementation", implementation );
911                     this.velocityContext.put( "smodel", sourceFileType );
912 
913                     this.editSourceFile( sourcesDirectory );
914                 }
915                 else
916                 {
917                     throw new IOException( getMessage( "implementationNotFound", implementation.getIdentifier() ) );
918                 }
919             }
920             finally
921             {
922                 this.specification = null;
923                 this.implementation = null;
924                 this.sourceFileType = null;
925                 this.velocityContext = null;
926             }
927         }
928 
929         /**
930          * Gets a list of sections added to the input.
931          * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you
932          * make to the returned list will be present inside the object. This is why there is no {@code set} method
933          * for the added sections property.</p>
934          *
935          * @return A list of sections added to the input.
936          *
937          * @deprecated As of JOMC 1.2, deprecated without replacement. This method will be removed in version 2.0.
938          */
939         @Deprecated
940         public List<Section> getAddedSections()
941         {
942             if ( this.addedSections == null )
943             {
944                 this.addedSections = new LinkedList<Section>();
945             }
946 
947             return this.addedSections;
948         }
949 
950         /**
951          * Gets a list of sections without corresponding model entry.
952          * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you
953          * make to the returned list will be present inside the object. This is why there is no {@code set} method
954          * for the unknown sections property.</p>
955          *
956          * @return A list of sections without corresponding model entry.
957          *
958          * @deprecated As of JOMC 1.2, deprecated without replacement. This method will be removed in version 2.0.
959          */
960         @Deprecated
961         public List<Section> getUnknownSections()
962         {
963             if ( this.unknownSections == null )
964             {
965                 this.unknownSections = new LinkedList<Section>();
966             }
967 
968             return this.unknownSections;
969         }
970 
971         /**
972          * Gets the currently edited source code file.
973          *
974          * @return The currently edited source code file.
975          *
976          * @deprecated As of JOMC 1.2, deprecated without replacement. This method will be removed in version 2.0.
977          */
978         @Deprecated
979         protected SourceFileType getSourceFileType()
980         {
981             if ( this.sourceFileType == null )
982             {
983                 if ( this.specification != null )
984                 {
985                     return SourceFileProcessor.this.getSourceFileType( this.specification );
986                 }
987 
988                 if ( this.implementation != null )
989                 {
990                     return SourceFileProcessor.this.getSourceFileType( this.implementation );
991                 }
992             }
993 
994             return this.sourceFileType;
995         }
996 
997         /**
998          * Gets a new velocity context used for merging templates.
999          *
1000          * @return A new velocity context used for merging templates.
1001          *
1002          * @throws IOException if creating a new context instance fails.
1003          * 
1004          * @deprecated As of JOMC 1.2, deprecated without replacement. This method will be removed in version 2.0.
1005          */
1006         @Deprecated
1007         protected VelocityContext getVelocityContext() throws IOException
1008         {
1009             if ( this.velocityContext == null )
1010             {
1011                 final VelocityContext ctx = SourceFileProcessor.this.getVelocityContext();
1012 
1013                 if ( this.specification != null )
1014                 {
1015                     ctx.put( "specification", this.specification );
1016                 }
1017 
1018                 if ( this.implementation != null )
1019                 {
1020                     ctx.put( "implementation", this.implementation );
1021                 }
1022 
1023                 return ctx;
1024             }
1025 
1026             return this.velocityContext;
1027         }
1028 
1029         /**
1030          * {@inheritDoc}
1031          * <p>This method creates any sections declared in the model of the source file as returned by method
1032          * {@code getSourceFileType} prior to rendering the output of the editor.</p>
1033          *
1034          * @param section The section to start rendering the editor's output with.
1035          *
1036          * @see #createSection(java.lang.String, java.lang.String, org.jomc.tools.model.SourceSectionType)
1037          */
1038         @Override
1039         protected String getOutput( final Section section ) throws IOException
1040         {
1041             this.getAddedSections().clear();
1042             this.getUnknownSections().clear();
1043 
1044             final SourceFileType model = this.getSourceFileType();
1045 
1046             if ( model != null )
1047             {
1048                 this.createSections( model, model.getSourceSections(), section );
1049             }
1050 
1051             return super.getOutput( section );
1052         }
1053 
1054         /**
1055          * {@inheritDoc}
1056          * <p>This method searches the model of the source file for a section matching {@code s} and updates properties
1057          * {@code headContent} and {@code tailContent} of {@code s} according to the templates declared in the model
1058          * as returned by method {@code getSourceFileType}.</p>
1059          *
1060          * @param s The section to edit.
1061          */
1062         @Override
1063         protected void editSection( final Section s ) throws IOException
1064         {
1065             try
1066             {
1067                 super.editSection( s );
1068 
1069                 final SourceFileType model = this.getSourceFileType();
1070 
1071                 if ( s.getName() != null && model != null && model.getSourceSections() != null )
1072                 {
1073                     final SourceSectionType sourceSectionType =
1074                         model.getSourceSections().getSourceSection( s.getName() );
1075 
1076                     if ( sourceSectionType != null )
1077                     {
1078                         if ( s.getStartingLine() != null )
1079                         {
1080                             s.setStartingLine( getIndentation( sourceSectionType.getIndentationLevel() )
1081                                                + s.getStartingLine().trim() );
1082 
1083                         }
1084                         if ( s.getEndingLine() != null )
1085                         {
1086                             s.setEndingLine( getIndentation( sourceSectionType.getIndentationLevel() )
1087                                              + s.getEndingLine().trim() );
1088 
1089                         }
1090 
1091                         if ( sourceSectionType.getHeadTemplate() != null
1092                              && ( !sourceSectionType.isEditable()
1093                                   || s.getHeadContent().toString().trim().length() == 0 ) )
1094                         {
1095                             final StringWriter writer = new StringWriter();
1096                             final Template template = getVelocityTemplate( sourceSectionType.getHeadTemplate() );
1097                             final VelocityContext ctx = getVelocityContext();
1098                             ctx.put( "template", template );
1099                             template.merge( ctx, writer );
1100                             writer.close();
1101                             s.getHeadContent().setLength( 0 );
1102                             s.getHeadContent().append( writer.toString() );
1103                         }
1104 
1105                         if ( sourceSectionType.getTailTemplate() != null
1106                              && ( !sourceSectionType.isEditable()
1107                                   || s.getTailContent().toString().trim().length() == 0 ) )
1108                         {
1109                             final StringWriter writer = new StringWriter();
1110                             final Template template = getVelocityTemplate( sourceSectionType.getTailTemplate() );
1111                             final VelocityContext ctx = getVelocityContext();
1112                             ctx.put( "template", template );
1113                             template.merge( ctx, writer );
1114                             writer.close();
1115                             s.getTailContent().setLength( 0 );
1116                             s.getTailContent().append( writer.toString() );
1117                         }
1118                     }
1119                     else
1120                     {
1121                         if ( isLoggable( Level.WARNING ) )
1122                         {
1123                             if ( this.implementation != null )
1124                             {
1125                                 log( Level.WARNING, getMessage(
1126                                     "unknownImplementationSection", this.implementation.getIdentifier(),
1127                                     model.getIdentifier(), s.getName() ), null );
1128 
1129 
1130                             }
1131                             else if ( this.specification != null )
1132                             {
1133                                 log( Level.WARNING, getMessage(
1134                                     "unknownSpecificationSection", this.specification.getIdentifier(),
1135                                     model.getIdentifier(), s.getName() ), null );
1136 
1137                             }
1138                         }
1139 
1140                         this.getUnknownSections().add( s );
1141                     }
1142                 }
1143             }
1144             catch ( final VelocityException e )
1145             {
1146                 // JDK: As of JDK 6, "new IOException( message, cause )".
1147                 throw (IOException) new IOException( getMessage( e ) ).initCause( e );
1148             }
1149         }
1150 
1151         private void createSections( final SourceFileType sourceFileType, final SourceSectionsType sourceSectionsType,
1152                                      final Section section ) throws IOException
1153         {
1154             if ( sourceSectionsType != null && section != null )
1155             {
1156                 for ( int i = 0, s0 = sourceSectionsType.getSourceSection().size(); i < s0; i++ )
1157                 {
1158                     final SourceSectionType sourceSectionType = sourceSectionsType.getSourceSection().get( i );
1159                     Section childSection = section.getSection( sourceSectionType.getName() );
1160 
1161                     if ( childSection == null && !sourceSectionType.isOptional() )
1162                     {
1163                         childSection = this.createSection( StringUtils.defaultString( sourceFileType.getHeadComment() ),
1164                                                            StringUtils.defaultString( sourceFileType.getTailComment() ),
1165                                                            sourceSectionType );
1166 
1167                         section.getSections().add( childSection );
1168 
1169                         if ( isLoggable( Level.FINE ) )
1170                         {
1171                             log( Level.FINE, getMessage(
1172                                 "addedSection", sourceFileType.getIdentifier(), childSection.getName() ), null );
1173 
1174                         }
1175 
1176                         this.getAddedSections().add( childSection );
1177                     }
1178 
1179                     this.createSections( sourceFileType, sourceSectionType.getSourceSections(), childSection );
1180                 }
1181             }
1182         }
1183 
1184         /**
1185          * Creates a new {@code Section} instance for a given {@code SourceSectionType}.
1186          *
1187          * @param headComment Characters to use to start a comment in the source file.
1188          * @param tailComment Characters to use to end a comment in the source file.
1189          * @param sourceSectionType The {@code SourceSectionType} to create a new {@code Section} instance for.
1190          *
1191          * @return A new {@code Section} instance for {@code sourceSectionType}.
1192          *
1193          * @throws NullPointerException if {@code headComment}, {@code tailComment} or {@code sourceSectionType} is
1194          * {@code null}.
1195          * @throws IOException if creating a new {@code Section} instance fails.
1196          *
1197          * @since 1.2
1198          */
1199         private Section createSection( final String headComment, final String tailComment,
1200                                        final SourceSectionType sourceSectionType ) throws IOException
1201         {
1202             if ( headComment == null )
1203             {
1204                 throw new NullPointerException( "headComment" );
1205             }
1206             if ( tailComment == null )
1207             {
1208                 throw new NullPointerException( "tailComment" );
1209             }
1210             if ( sourceSectionType == null )
1211             {
1212                 throw new NullPointerException( "sourceSectionType" );
1213             }
1214 
1215             final Section s = new Section();
1216             s.setName( sourceSectionType.getName() );
1217 
1218             final StringBuilder head = new StringBuilder( 255 );
1219             head.append( getIndentation( sourceSectionType.getIndentationLevel() ) ).append( headComment );
1220 
1221             s.setStartingLine( head + " SECTION-START[" + sourceSectionType.getName() + ']' + tailComment );
1222             s.setEndingLine( head + " SECTION-END" + tailComment );
1223 
1224             return s;
1225         }
1226 
1227         private void editSourceFile( final File sourcesDirectory ) throws IOException
1228         {
1229             if ( sourcesDirectory == null )
1230             {
1231                 throw new NullPointerException( "sourcesDirectory" );
1232             }
1233             if ( !sourcesDirectory.isDirectory() )
1234             {
1235                 throw new IOException( getMessage( "directoryNotFound", sourcesDirectory.getAbsolutePath() ) );
1236             }
1237 
1238             final SourceFileType model = this.getSourceFileType();
1239 
1240             if ( model != null && model.getLocation() != null )
1241             {
1242                 final File f = new File( sourcesDirectory, model.getLocation() );
1243 
1244                 try
1245                 {
1246                     String content = "";
1247                     String edited = null;
1248                     boolean creating = false;
1249 
1250                     if ( !f.exists() )
1251                     {
1252                         if ( model.getTemplate() != null )
1253                         {
1254                             final StringWriter writer = new StringWriter();
1255                             final Template template = getVelocityTemplate( model.getTemplate() );
1256                             final VelocityContext ctx = this.getVelocityContext();
1257                             ctx.put( "template", template );
1258                             template.merge( ctx, writer );
1259                             writer.close();
1260                             content = writer.toString();
1261                             creating = true;
1262                         }
1263                     }
1264                     else
1265                     {
1266                         if ( isLoggable( Level.FINER ) )
1267                         {
1268                             log( Level.FINER, getMessage( "reading", f.getAbsolutePath() ), null );
1269                         }
1270 
1271                         content = this.readSourceFile( f );
1272                     }
1273 
1274                     try
1275                     {
1276                         edited = super.edit( content );
1277                     }
1278                     catch ( final IOException e )
1279                     {
1280                         // JDK: As of JDK 6, "new IOException( message, cause )".
1281                         throw (IOException) new IOException( getMessage(
1282                             "failedEditing", f.getAbsolutePath(), getMessage( e ) ) ).initCause( e );
1283 
1284                     }
1285 
1286                     if ( !edited.equals( content ) || edited.length() == 0 )
1287                     {
1288                         if ( !f.getParentFile().exists() && !f.getParentFile().mkdirs() )
1289                         {
1290                             throw new IOException( getMessage(
1291                                 "failedCreatingDirectory", f.getParentFile().getAbsolutePath() ) );
1292 
1293                         }
1294 
1295                         if ( isLoggable( Level.INFO ) )
1296                         {
1297                             log( Level.INFO, getMessage(
1298                                 creating ? "creating" : "editing", f.getAbsolutePath() ), null );
1299 
1300                         }
1301 
1302                         this.writeSourceFile( f, edited );
1303                     }
1304                     else if ( isLoggable( Level.FINER ) )
1305                     {
1306                         log( Level.FINER, getMessage( "unchanged", f.getAbsolutePath() ), null );
1307                     }
1308                 }
1309                 catch ( final VelocityException e )
1310                 {
1311                     // JDK: As of JDK 6, "new IOException( message, cause )".
1312                     throw (IOException) new IOException( getMessage(
1313                         "failedEditing", f.getAbsolutePath(), getMessage( e ) ) ).initCause( e );
1314 
1315                 }
1316             }
1317         }
1318 
1319         private String readSourceFile( final File file ) throws IOException
1320         {
1321             if ( file == null )
1322             {
1323                 throw new NullPointerException( "file" );
1324             }
1325 
1326             RandomAccessFile randomAccessFile = null;
1327             FileChannel fileChannel = null;
1328             FileLock fileLock = null;
1329             boolean suppressExceptionOnClose = true;
1330 
1331             //final Charset charset = Charset.forName( getInputEncoding() );
1332             final int length = file.length() > 0L ? Long.valueOf( file.length() ).intValue() : 1;
1333             final ByteBuffer buf = ByteBuffer.allocate( length );
1334             final StringBuilder appendable = new StringBuilder( length );
1335 
1336             try
1337             {
1338                 randomAccessFile = new RandomAccessFile( file, "r" );
1339                 fileChannel = randomAccessFile.getChannel();
1340                 fileLock = fileChannel.lock( 0L, file.length(), true );
1341                 fileChannel.position( 0L );
1342 
1343                 buf.clear();
1344                 int read = fileChannel.read( buf );
1345 
1346                 while ( read != -1 )
1347                 {
1348                     // JDK: As of JDK 6, new String( byte[], int, int, Charset )
1349                     appendable.append( new String( buf.array(), buf.arrayOffset(), read, getInputEncoding() ) );
1350                     buf.clear();
1351                     read = fileChannel.read( buf );
1352                 }
1353 
1354                 suppressExceptionOnClose = false;
1355                 return appendable.toString();
1356             }
1357             finally
1358             {
1359                 this.releaseAndClose( fileLock, fileChannel, randomAccessFile, suppressExceptionOnClose );
1360             }
1361         }
1362 
1363         private void writeSourceFile( final File file, final String content ) throws IOException
1364         {
1365             if ( file == null )
1366             {
1367                 throw new NullPointerException( "file" );
1368             }
1369             if ( content == null )
1370             {
1371                 throw new NullPointerException( "content" );
1372             }
1373 
1374             RandomAccessFile randomAccessFile = null;
1375             FileChannel fileChannel = null;
1376             FileLock fileLock = null;
1377             boolean suppressExceptionOnClose = true;
1378             final byte[] bytes = content.getBytes( getOutputEncoding() );
1379 
1380             try
1381             {
1382                 randomAccessFile = new RandomAccessFile( file, "rw" );
1383                 fileChannel = randomAccessFile.getChannel();
1384                 fileLock = fileChannel.lock( 0L, bytes.length, false );
1385                 fileChannel.truncate( bytes.length );
1386                 fileChannel.position( 0L );
1387                 fileChannel.write( ByteBuffer.wrap( bytes ) );
1388                 fileChannel.force( true );
1389                 suppressExceptionOnClose = false;
1390             }
1391             finally
1392             {
1393                 this.releaseAndClose( fileLock, fileChannel, randomAccessFile, suppressExceptionOnClose );
1394             }
1395         }
1396 
1397         private void releaseAndClose( final FileLock fileLock, final FileChannel fileChannel,
1398                                       final RandomAccessFile randomAccessFile, final boolean suppressExceptions )
1399             throws IOException
1400         {
1401             try
1402             {
1403                 if ( fileLock != null )
1404                 {
1405                     fileLock.release();
1406                 }
1407             }
1408             catch ( final IOException e )
1409             {
1410                 if ( suppressExceptions )
1411                 {
1412                     log( Level.SEVERE, null, e );
1413                 }
1414                 else
1415                 {
1416                     throw e;
1417                 }
1418             }
1419             finally
1420             {
1421                 try
1422                 {
1423                     if ( fileChannel != null )
1424                     {
1425                         fileChannel.close();
1426                     }
1427                 }
1428                 catch ( final IOException e )
1429                 {
1430                     if ( suppressExceptions )
1431                     {
1432                         log( Level.SEVERE, null, e );
1433                     }
1434                     else
1435                     {
1436                         throw e;
1437                     }
1438                 }
1439                 finally
1440                 {
1441                     try
1442                     {
1443                         if ( randomAccessFile != null )
1444                         {
1445                             randomAccessFile.close();
1446                         }
1447                     }
1448                     catch ( final IOException e )
1449                     {
1450                         if ( suppressExceptions )
1451                         {
1452                             log( Level.SEVERE, null, e );
1453                         }
1454                         else
1455                         {
1456                             throw e;
1457                         }
1458                     }
1459                 }
1460             }
1461         }
1462 
1463     }
1464 
1465 }