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 4579 2012-06-03 00:28:14Z schulte2005 $
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:schulte2005@users.sourceforge.net">Christian Schulte</a>
74   * @version $JOMC: SourceFileProcessor.java 4579 2012-06-03 00:28:14Z schulte2005 $
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:schulte2005@users.sourceforge.net">Christian Schulte</a>
601      * @version $JOMC: SourceFileProcessor.java 4579 2012-06-03 00:28:14Z schulte2005 $
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             if ( getModules() != null
847                  && getModules().getSpecification( specification.getIdentifier() ) != null )
848             {
849                 this.specification = specification;
850                 this.sourceFileType = sourceFileType;
851                 this.velocityContext = SourceFileProcessor.this.getVelocityContext();
852                 this.velocityContext.put( "specification", specification );
853                 this.velocityContext.put( "smodel", sourceFileType );
854 
855                 this.editSourceFile( sourcesDirectory );
856 
857                 this.implementation = null;
858                 this.specification = null;
859                 this.sourceFileType = null;
860                 this.velocityContext = null;
861             }
862             else
863             {
864                 throw new IOException( getMessage( "specificationNotFound", specification.getIdentifier() ) );
865             }
866         }
867 
868         /**
869          * Edits a source file of a given implementation.
870          *
871          * @param implementation The implementation to edit a source file of.
872          * @param sourceFileType The model of the source file to edit.
873          * @param sourcesDirectory The directory holding the source file to edit.
874          *
875          * @throws NullPointerException if {@code implementation}, {@code sourceFileType} or {@code sourcesDirectory} is
876          * {@code null}.
877          * @throws IOException if editing fails.
878          *
879          * @since 1.2
880          */
881         public final void edit( final Implementation implementation, final SourceFileType sourceFileType,
882                                 final File sourcesDirectory ) throws IOException
883         {
884             if ( implementation == null )
885             {
886                 throw new NullPointerException( "implementation" );
887             }
888             if ( sourceFileType == null )
889             {
890                 throw new NullPointerException( "sourceFileType" );
891             }
892             if ( sourcesDirectory == null )
893             {
894                 throw new NullPointerException( "sourcesDirectory" );
895             }
896 
897             if ( getModules() != null
898                  && getModules().getImplementation( implementation.getIdentifier() ) != null )
899             {
900                 this.implementation = implementation;
901                 this.sourceFileType = sourceFileType;
902                 this.velocityContext = SourceFileProcessor.this.getVelocityContext();
903                 this.velocityContext.put( "implementation", implementation );
904                 this.velocityContext.put( "smodel", sourceFileType );
905 
906                 this.editSourceFile( sourcesDirectory );
907 
908                 this.implementation = null;
909                 this.specification = null;
910                 this.sourceFileType = null;
911                 this.velocityContext = null;
912             }
913             else
914             {
915                 throw new IOException( getMessage( "implementationNotFound", implementation.getIdentifier() ) );
916             }
917         }
918 
919         /**
920          * Gets a list of sections added to the input.
921          * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you
922          * make to the returned list will be present inside the object. This is why there is no {@code set} method
923          * for the added sections property.</p>
924          *
925          * @return A list of sections added to the input.
926          *
927          * @deprecated As of JOMC 1.2, deprecated without replacement. This method will be removed in version 2.0.
928          */
929         @Deprecated
930         public List<Section> getAddedSections()
931         {
932             if ( this.addedSections == null )
933             {
934                 this.addedSections = new LinkedList<Section>();
935             }
936 
937             return this.addedSections;
938         }
939 
940         /**
941          * Gets a list of sections without corresponding model entry.
942          * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you
943          * make to the returned list will be present inside the object. This is why there is no {@code set} method
944          * for the unknown sections property.</p>
945          *
946          * @return A list of sections without corresponding model entry.
947          *
948          * @deprecated As of JOMC 1.2, deprecated without replacement. This method will be removed in version 2.0.
949          */
950         @Deprecated
951         public List<Section> getUnknownSections()
952         {
953             if ( this.unknownSections == null )
954             {
955                 this.unknownSections = new LinkedList<Section>();
956             }
957 
958             return this.unknownSections;
959         }
960 
961         /**
962          * Gets the currently edited source code file.
963          *
964          * @return The currently edited source code file.
965          *
966          * @deprecated As of JOMC 1.2, deprecated without replacement. This method will be removed in version 2.0.
967          */
968         @Deprecated
969         protected SourceFileType getSourceFileType()
970         {
971             if ( this.sourceFileType == null )
972             {
973                 if ( this.specification != null )
974                 {
975                     return SourceFileProcessor.this.getSourceFileType( this.specification );
976                 }
977 
978                 if ( this.implementation != null )
979                 {
980                     return SourceFileProcessor.this.getSourceFileType( this.implementation );
981                 }
982             }
983 
984             return this.sourceFileType;
985         }
986 
987         /**
988          * Gets a new velocity context used for merging templates.
989          *
990          * @return A new velocity context used for merging templates.
991          *
992          * @throws IOException if creating a new context instance fails.
993          * 
994          * @deprecated As of JOMC 1.2, deprecated without replacement. This method will be removed in version 2.0.
995          */
996         @Deprecated
997         protected VelocityContext getVelocityContext() throws IOException
998         {
999             if ( this.velocityContext == null )
1000             {
1001                 final VelocityContext ctx = SourceFileProcessor.this.getVelocityContext();
1002 
1003                 if ( this.specification != null )
1004                 {
1005                     ctx.put( "specification", this.specification );
1006                 }
1007 
1008                 if ( this.implementation != null )
1009                 {
1010                     ctx.put( "implementation", this.implementation );
1011                 }
1012 
1013                 return ctx;
1014             }
1015 
1016             return this.velocityContext;
1017         }
1018 
1019         /**
1020          * {@inheritDoc}
1021          * <p>This method creates any sections declared in the model of the source file as returned by method
1022          * {@code getSourceFileType} prior to rendering the output of the editor.</p>
1023          *
1024          * @param section The section to start rendering the editor's output with.
1025          *
1026          * @see #createSection(java.lang.String, java.lang.String, org.jomc.tools.model.SourceSectionType)
1027          */
1028         @Override
1029         protected String getOutput( final Section section ) throws IOException
1030         {
1031             this.getAddedSections().clear();
1032             this.getUnknownSections().clear();
1033 
1034             final SourceFileType model = this.getSourceFileType();
1035 
1036             if ( model != null )
1037             {
1038                 this.createSections( model, model.getSourceSections(), section );
1039             }
1040 
1041             return super.getOutput( section );
1042         }
1043 
1044         /**
1045          * {@inheritDoc}
1046          * <p>This method searches the model of the source file for a section matching {@code s} and updates properties
1047          * {@code headContent} and {@code tailContent} of {@code s} according to the templates declared in the model
1048          * as returned by method {@code getSourceFileType}.</p>
1049          *
1050          * @param s The section to edit.
1051          */
1052         @Override
1053         protected void editSection( final Section s ) throws IOException
1054         {
1055             try
1056             {
1057                 super.editSection( s );
1058 
1059                 final SourceFileType model = this.getSourceFileType();
1060 
1061                 if ( s.getName() != null && model != null && model.getSourceSections() != null )
1062                 {
1063                     final SourceSectionType sourceSectionType =
1064                         model.getSourceSections().getSourceSection( s.getName() );
1065 
1066                     if ( sourceSectionType != null )
1067                     {
1068                         if ( s.getStartingLine() != null )
1069                         {
1070                             s.setStartingLine( getIndentation( sourceSectionType.getIndentationLevel() )
1071                                                + s.getStartingLine().trim() );
1072 
1073                         }
1074                         if ( s.getEndingLine() != null )
1075                         {
1076                             s.setEndingLine( getIndentation( sourceSectionType.getIndentationLevel() )
1077                                              + s.getEndingLine().trim() );
1078 
1079                         }
1080 
1081                         if ( sourceSectionType.getHeadTemplate() != null
1082                              && ( !sourceSectionType.isEditable()
1083                                   || s.getHeadContent().toString().trim().length() == 0 ) )
1084                         {
1085                             final StringWriter writer = new StringWriter();
1086                             final Template template = getVelocityTemplate( sourceSectionType.getHeadTemplate() );
1087                             final VelocityContext ctx = getVelocityContext();
1088                             ctx.put( "template", template );
1089                             template.merge( ctx, writer );
1090                             writer.close();
1091                             s.getHeadContent().setLength( 0 );
1092                             s.getHeadContent().append( writer.toString() );
1093                         }
1094 
1095                         if ( sourceSectionType.getTailTemplate() != null
1096                              && ( !sourceSectionType.isEditable()
1097                                   || s.getTailContent().toString().trim().length() == 0 ) )
1098                         {
1099                             final StringWriter writer = new StringWriter();
1100                             final Template template = getVelocityTemplate( sourceSectionType.getTailTemplate() );
1101                             final VelocityContext ctx = getVelocityContext();
1102                             ctx.put( "template", template );
1103                             template.merge( ctx, writer );
1104                             writer.close();
1105                             s.getTailContent().setLength( 0 );
1106                             s.getTailContent().append( writer.toString() );
1107                         }
1108                     }
1109                     else
1110                     {
1111                         if ( isLoggable( Level.WARNING ) )
1112                         {
1113                             if ( this.implementation != null )
1114                             {
1115                                 log( Level.WARNING, getMessage(
1116                                     "unknownImplementationSection", this.implementation.getIdentifier(),
1117                                     model.getIdentifier(), s.getName() ), null );
1118 
1119 
1120                             }
1121                             else if ( this.specification != null )
1122                             {
1123                                 log( Level.WARNING, getMessage(
1124                                     "unknownSpecificationSection", this.specification.getIdentifier(),
1125                                     model.getIdentifier(), s.getName() ), null );
1126 
1127                             }
1128                         }
1129 
1130                         this.getUnknownSections().add( s );
1131                     }
1132                 }
1133             }
1134             catch ( final VelocityException e )
1135             {
1136                 // JDK: As of JDK 6, "new IOException( message, cause )".
1137                 throw (IOException) new IOException( getMessage( e ) ).initCause( e );
1138             }
1139         }
1140 
1141         private void createSections( final SourceFileType sourceFileType, final SourceSectionsType sourceSectionsType,
1142                                      final Section section ) throws IOException
1143         {
1144             if ( sourceSectionsType != null && section != null )
1145             {
1146                 for ( int i = 0, s0 = sourceSectionsType.getSourceSection().size(); i < s0; i++ )
1147                 {
1148                     final SourceSectionType sourceSectionType = sourceSectionsType.getSourceSection().get( i );
1149                     Section childSection = section.getSection( sourceSectionType.getName() );
1150 
1151                     if ( childSection == null && !sourceSectionType.isOptional() )
1152                     {
1153                         childSection = this.createSection( StringUtils.defaultString( sourceFileType.getHeadComment() ),
1154                                                            StringUtils.defaultString( sourceFileType.getTailComment() ),
1155                                                            sourceSectionType );
1156 
1157                         section.getSections().add( childSection );
1158 
1159                         if ( isLoggable( Level.FINE ) )
1160                         {
1161                             log( Level.FINE, getMessage(
1162                                 "addedSection", sourceFileType.getIdentifier(), childSection.getName() ), null );
1163 
1164                         }
1165 
1166                         this.getAddedSections().add( childSection );
1167                     }
1168 
1169                     this.createSections( sourceFileType, sourceSectionType.getSourceSections(), childSection );
1170                 }
1171             }
1172         }
1173 
1174         /**
1175          * Creates a new {@code Section} instance for a given {@code SourceSectionType}.
1176          *
1177          * @param headComment Characters to use to start a comment in the source file.
1178          * @param tailComment Characters to use to end a comment in the source file.
1179          * @param sourceSectionType The {@code SourceSectionType} to create a new {@code Section} instance for.
1180          *
1181          * @return A new {@code Section} instance for {@code sourceSectionType}.
1182          *
1183          * @throws NullPointerException if {@code headComment}, {@code tailComment} or {@code sourceSectionType} is
1184          * {@code null}.
1185          * @throws IOException if creating a new {@code Section} instance fails.
1186          *
1187          * @since 1.2
1188          */
1189         private Section createSection( final String headComment, final String tailComment,
1190                                        final SourceSectionType sourceSectionType ) throws IOException
1191         {
1192             if ( headComment == null )
1193             {
1194                 throw new NullPointerException( "headComment" );
1195             }
1196             if ( tailComment == null )
1197             {
1198                 throw new NullPointerException( "tailComment" );
1199             }
1200             if ( sourceSectionType == null )
1201             {
1202                 throw new NullPointerException( "sourceSectionType" );
1203             }
1204 
1205             final Section s = new Section();
1206             s.setName( sourceSectionType.getName() );
1207 
1208             final StringBuilder head = new StringBuilder( 255 );
1209             head.append( getIndentation( sourceSectionType.getIndentationLevel() ) ).append( headComment );
1210 
1211             s.setStartingLine( head + " SECTION-START[" + sourceSectionType.getName() + ']' + tailComment );
1212             s.setEndingLine( head + " SECTION-END" + tailComment );
1213 
1214             return s;
1215         }
1216 
1217         private void editSourceFile( final File sourcesDirectory ) throws IOException
1218         {
1219             if ( sourcesDirectory == null )
1220             {
1221                 throw new NullPointerException( "sourcesDirectory" );
1222             }
1223             if ( !sourcesDirectory.isDirectory() )
1224             {
1225                 throw new IOException( getMessage( "directoryNotFound", sourcesDirectory.getAbsolutePath() ) );
1226             }
1227 
1228             final SourceFileType model = this.getSourceFileType();
1229 
1230             if ( model != null && model.getLocation() != null )
1231             {
1232                 final File f = new File( sourcesDirectory, model.getLocation() );
1233 
1234                 try
1235                 {
1236                     String content = "";
1237                     String edited = null;
1238                     boolean creating = false;
1239 
1240                     if ( !f.exists() )
1241                     {
1242                         if ( model.getTemplate() != null )
1243                         {
1244                             final StringWriter writer = new StringWriter();
1245                             final Template template = getVelocityTemplate( model.getTemplate() );
1246                             final VelocityContext ctx = this.getVelocityContext();
1247                             ctx.put( "template", template );
1248                             template.merge( ctx, writer );
1249                             writer.close();
1250                             content = writer.toString();
1251                             creating = true;
1252                         }
1253                     }
1254                     else
1255                     {
1256                         if ( isLoggable( Level.FINER ) )
1257                         {
1258                             log( Level.FINER, getMessage( "reading", f.getAbsolutePath() ), null );
1259                         }
1260 
1261                         content = this.readSourceFile( f );
1262                     }
1263 
1264                     try
1265                     {
1266                         edited = super.edit( content );
1267                     }
1268                     catch ( final IOException e )
1269                     {
1270                         // JDK: As of JDK 6, "new IOException( message, cause )".
1271                         throw (IOException) new IOException( getMessage(
1272                             "failedEditing", f.getAbsolutePath(), getMessage( e ) ) ).initCause( e );
1273 
1274                     }
1275 
1276                     if ( !edited.equals( content ) || edited.length() == 0 )
1277                     {
1278                         if ( !f.getParentFile().exists() && !f.getParentFile().mkdirs() )
1279                         {
1280                             throw new IOException( getMessage(
1281                                 "failedCreatingDirectory", f.getParentFile().getAbsolutePath() ) );
1282 
1283                         }
1284 
1285                         if ( isLoggable( Level.INFO ) )
1286                         {
1287                             log( Level.INFO, getMessage(
1288                                 creating ? "creating" : "editing", f.getAbsolutePath() ), null );
1289 
1290                         }
1291 
1292                         this.writeSourceFile( f, edited );
1293                     }
1294                     else if ( isLoggable( Level.FINER ) )
1295                     {
1296                         log( Level.FINER, getMessage( "unchanged", f.getAbsolutePath() ), null );
1297                     }
1298                 }
1299                 catch ( final VelocityException e )
1300                 {
1301                     // JDK: As of JDK 6, "new IOException( message, cause )".
1302                     throw (IOException) new IOException( getMessage(
1303                         "failedEditing", f.getAbsolutePath(), getMessage( e ) ) ).initCause( e );
1304 
1305                 }
1306             }
1307         }
1308 
1309         private String readSourceFile( final File file ) throws IOException
1310         {
1311             if ( file == null )
1312             {
1313                 throw new NullPointerException( "file" );
1314             }
1315 
1316             RandomAccessFile randomAccessFile = null;
1317             FileChannel fileChannel = null;
1318             FileLock fileLock = null;
1319             boolean suppressExceptionOnClose = true;
1320 
1321             //final Charset charset = Charset.forName( getInputEncoding() );
1322             final int length = file.length() > 0L ? Long.valueOf( file.length() ).intValue() : 1;
1323             final ByteBuffer buf = ByteBuffer.allocate( length );
1324             final StringBuilder appendable = new StringBuilder( length );
1325 
1326             try
1327             {
1328                 randomAccessFile = new RandomAccessFile( file, "r" );
1329                 fileChannel = randomAccessFile.getChannel();
1330                 fileLock = fileChannel.lock( 0L, file.length(), true );
1331                 fileChannel.position( 0L );
1332 
1333                 buf.clear();
1334                 int read = fileChannel.read( buf );
1335 
1336                 while ( read != -1 )
1337                 {
1338                     // JDK: As of JDK 6, new String( byte[], int, int, Charset )
1339                     appendable.append( new String( buf.array(), buf.arrayOffset(), read, getInputEncoding() ) );
1340                     buf.clear();
1341                     read = fileChannel.read( buf );
1342                 }
1343 
1344                 suppressExceptionOnClose = false;
1345                 return appendable.toString();
1346             }
1347             finally
1348             {
1349                 this.releaseAndClose( fileLock, fileChannel, randomAccessFile, suppressExceptionOnClose );
1350             }
1351         }
1352 
1353         private void writeSourceFile( final File file, final String content ) throws IOException
1354         {
1355             if ( file == null )
1356             {
1357                 throw new NullPointerException( "file" );
1358             }
1359             if ( content == null )
1360             {
1361                 throw new NullPointerException( "content" );
1362             }
1363 
1364             RandomAccessFile randomAccessFile = null;
1365             FileChannel fileChannel = null;
1366             FileLock fileLock = null;
1367             boolean suppressExceptionOnClose = true;
1368             final byte[] bytes = content.getBytes( getOutputEncoding() );
1369 
1370             try
1371             {
1372                 randomAccessFile = new RandomAccessFile( file, "rw" );
1373                 fileChannel = randomAccessFile.getChannel();
1374                 fileLock = fileChannel.lock( 0L, bytes.length, false );
1375                 fileChannel.truncate( bytes.length );
1376                 fileChannel.position( 0L );
1377                 fileChannel.write( ByteBuffer.wrap( bytes ) );
1378                 fileChannel.force( true );
1379                 suppressExceptionOnClose = false;
1380             }
1381             finally
1382             {
1383                 this.releaseAndClose( fileLock, fileChannel, randomAccessFile, suppressExceptionOnClose );
1384             }
1385         }
1386 
1387         private void releaseAndClose( final FileLock fileLock, final FileChannel fileChannel,
1388                                       final RandomAccessFile randomAccessFile, final boolean suppressExceptions )
1389             throws IOException
1390         {
1391             try
1392             {
1393                 if ( fileLock != null )
1394                 {
1395                     fileLock.release();
1396                 }
1397             }
1398             catch ( final IOException e )
1399             {
1400                 if ( suppressExceptions )
1401                 {
1402                     log( Level.SEVERE, null, e );
1403                 }
1404                 else
1405                 {
1406                     throw e;
1407                 }
1408             }
1409             finally
1410             {
1411                 try
1412                 {
1413                     if ( fileChannel != null )
1414                     {
1415                         fileChannel.close();
1416                     }
1417                 }
1418                 catch ( final IOException e )
1419                 {
1420                     if ( suppressExceptions )
1421                     {
1422                         log( Level.SEVERE, null, e );
1423                     }
1424                     else
1425                     {
1426                         throw e;
1427                     }
1428                 }
1429                 finally
1430                 {
1431                     try
1432                     {
1433                         if ( randomAccessFile != null )
1434                         {
1435                             randomAccessFile.close();
1436                         }
1437                     }
1438                     catch ( final IOException e )
1439                     {
1440                         if ( suppressExceptions )
1441                         {
1442                             log( Level.SEVERE, null, e );
1443                         }
1444                         else
1445                         {
1446                             throw e;
1447                         }
1448                     }
1449                 }
1450             }
1451         }
1452 
1453     }
1454 
1455 }