View Javadoc
1   /*
2    * Copyright (C) 2009 Christian Schulte <cs@schulte.it>
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *   o Redistributions of source code must retain the above copyright
10   *     notice, this list of conditions and the following disclaimer.
11   *
12   *   o Redistributions in binary form must reproduce the above copyright
13   *     notice, this list of conditions and the following disclaimer in
14   *     the documentation and/or other materials provided with the
15   *     distribution.
16   *
17   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19   * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20   * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   *
28   * $JOMC: AbstractJomcToolCommand.java 5299 2016-08-30 01:50:13Z schulte $
29   *
30   */
31  package org.jomc.cli.commands;
32  
33  import java.io.File;
34  import java.net.MalformedURLException;
35  import java.net.URL;
36  import java.util.Locale;
37  import java.util.logging.Level;
38  import org.apache.commons.cli.CommandLine;
39  import org.apache.commons.lang.StringEscapeUtils;
40  import org.apache.commons.lang.StringUtils;
41  import org.jomc.model.Implementation;
42  import org.jomc.model.Module;
43  import org.jomc.model.Modules;
44  import org.jomc.model.Specification;
45  import org.jomc.model.modlet.ModelHelper;
46  import org.jomc.modlet.Model;
47  import org.jomc.tools.JomcTool;
48  
49  /**
50   * {@code JomcTool} based command implementation.
51   *
52   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
53   */
54  public abstract class AbstractJomcToolCommand extends AbstractModelCommand
55  {
56  
57      /**
58       * Creates a new {@code AbstractJomcToolCommand} instance.
59       */
60      public AbstractJomcToolCommand()
61      {
62          super();
63      }
64  
65      @Override
66      public org.apache.commons.cli.Options getOptions()
67      {
68          final org.apache.commons.cli.Options options = super.getOptions();
69          options.addOption( Options.TEMPLATE_PROFILE_OPTION );
70          options.addOption( Options.DEFAULT_TEMPLATE_PROFILE_OPTION );
71          options.addOption( Options.DEFAULT_TEMPLATE_ENCODING_OPTION );
72          options.addOption( Options.TEMPLATE_LOCATION_OPTION );
73          options.addOption( Options.OUTPUT_ENCODING_OPTION );
74          options.addOption( Options.INPUT_ENCODING_OPTION );
75          options.addOption( Options.INDENTATION_STRING_OPTION );
76          options.addOption( Options.LINE_SEPARATOR_OPTION );
77          options.addOption( Options.LANGUAGE_OPTION );
78          options.addOption( Options.COUNTRY_OPTION );
79          options.addOption( Options.LOCALE_VARIANT_OPTION );
80          options.addOption( Options.IMPLEMENTATION_OPTION );
81          options.addOption( Options.MODULE_OPTION );
82          options.addOption( Options.SPECIFICATION_OPTION );
83          return options;
84      }
85  
86      /**
87       * Creates a new object for a given class name and type.
88       *
89       * @param className The name of the class to create an object of.
90       * @param type The class of the type of object to create.
91       * @param <T> The type of the object to create.
92       *
93       * @return A new instance of the class with name {@code className}.
94       *
95       * @throws NullPointerException if {@code className} or {@code type} is {@code null}.
96       * @throws CommandExecutionException if creating a new object fails.
97       */
98      protected <T> T createObject( final String className, final Class<T> type ) throws CommandExecutionException
99      {
100         if ( className == null )
101         {
102             throw new NullPointerException( "className" );
103         }
104         if ( type == null )
105         {
106             throw new NullPointerException( "type" );
107         }
108 
109         try
110         {
111             return Class.forName( className ).asSubclass( type ).newInstance();
112         }
113         catch ( final InstantiationException e )
114         {
115             throw new CommandExecutionException( Messages.getMessage( "objectCreationFailure", className ), e );
116         }
117         catch ( final IllegalAccessException e )
118         {
119             throw new CommandExecutionException( Messages.getMessage( "objectCreationFailure", className ), e );
120         }
121         catch ( final ClassNotFoundException e )
122         {
123             throw new CommandExecutionException( Messages.getMessage( "objectCreationFailure", className ), e );
124         }
125         catch ( final ClassCastException e )
126         {
127             throw new CommandExecutionException( Messages.getMessage( "objectCreationFailure", className ), e );
128         }
129     }
130 
131     /**
132      * Creates a new {@code JomcTool} object for a given class name and type.
133      *
134      * @param commandLine The {@code CommandLine} to configure the new {@code JomcTool} object with.
135      * @param className The name of the class to create an object of.
136      * @param type The class of the type of object to create.
137      * @param <T> The type of the object to create.
138      *
139      * @return A new instance of the class with name {@code className} configured using {@code commandLine}.
140      *
141      * @throws NullPointerException if {@code commandLine}, {@code className} or {@code type} is {@code null}.
142      * @throws CommandExecutionException if creating a new object fails.
143      *
144      * @see #createObject(java.lang.String, java.lang.Class)
145      */
146     protected <T extends JomcTool> T createJomcTool( final String className, final Class<T> type,
147                                                      final CommandLine commandLine ) throws CommandExecutionException
148     {
149         if ( commandLine == null )
150         {
151             throw new NullPointerException( "commandLine" );
152         }
153         if ( className == null )
154         {
155             throw new NullPointerException( "className" );
156         }
157         if ( type == null )
158         {
159             throw new NullPointerException( "type" );
160         }
161 
162         final T tool = this.createObject( className, type );
163         tool.setLogLevel( this.getLogLevel() );
164         tool.setExecutorService( this.getExecutorService( commandLine ) );
165         tool.setLocale( this.getLocale( commandLine ) );
166         tool.getListeners().add( new JomcTool.Listener()
167         {
168 
169             @Override
170             public void onLog( final Level level, final String message, final Throwable throwable )
171             {
172                 super.onLog( level, message, throwable );
173                 log( level, message, throwable );
174             }
175 
176         } );
177 
178         if ( commandLine.hasOption( Options.TEMPLATE_ENCODING_OPTION.getOpt() ) )
179         {
180             this.log( Level.WARNING, Messages.getMessage( "deprecatedOptionMessage",
181                                                           Options.TEMPLATE_ENCODING_OPTION.getLongOpt(),
182                                                           Options.DEFAULT_TEMPLATE_ENCODING_OPTION.getLongOpt() ),
183                       null );
184 
185             tool.setDefaultTemplateEncoding( commandLine.getOptionValue( Options.TEMPLATE_ENCODING_OPTION.getOpt() ) );
186         }
187         else if ( commandLine.hasOption( Options.DEFAULT_TEMPLATE_ENCODING_OPTION.getOpt() ) )
188         {
189             tool.setDefaultTemplateEncoding(
190                 commandLine.getOptionValue( Options.DEFAULT_TEMPLATE_ENCODING_OPTION.getOpt() ) );
191 
192         }
193         if ( commandLine.hasOption( Options.DEFAULT_TEMPLATE_PROFILE_OPTION.getOpt() ) )
194         {
195             tool.setDefaultTemplateProfile(
196                 commandLine.getOptionValue( Options.DEFAULT_TEMPLATE_PROFILE_OPTION.getOpt() ) );
197 
198         }
199         if ( commandLine.hasOption( Options.TEMPLATE_PROFILE_OPTION.getOpt() ) )
200         {
201             tool.setTemplateProfile( commandLine.getOptionValue( Options.TEMPLATE_PROFILE_OPTION.getOpt() ) );
202         }
203         if ( commandLine.hasOption( Options.TEMPLATE_LOCATION_OPTION.getOpt() ) )
204         {
205             try
206             {
207                 tool.setTemplateLocation( new URL(
208                     commandLine.getOptionValue( Options.TEMPLATE_LOCATION_OPTION.getOpt() ) ) );
209 
210             }
211             catch ( final MalformedURLException e )
212             {
213                 this.log( Level.FINER, null, e );
214 
215                 try
216                 {
217                     tool.setTemplateLocation( new File(
218                         commandLine.getOptionValue( Options.TEMPLATE_LOCATION_OPTION.getOpt() ) ).toURI().toURL() );
219 
220                 }
221                 catch ( final MalformedURLException e2 )
222                 {
223                     throw new CommandExecutionException( Messages.getMessage( e2 ), e2 );
224                 }
225             }
226         }
227         if ( commandLine.hasOption( Options.INPUT_ENCODING_OPTION.getOpt() ) )
228         {
229             tool.setInputEncoding( commandLine.getOptionValue( Options.INPUT_ENCODING_OPTION.getOpt() ) );
230         }
231         if ( commandLine.hasOption( Options.OUTPUT_ENCODING_OPTION.getOpt() ) )
232         {
233             tool.setOutputEncoding( commandLine.getOptionValue( Options.OUTPUT_ENCODING_OPTION.getOpt() ) );
234         }
235         if ( commandLine.hasOption( Options.INDENTATION_STRING_OPTION.getOpt() ) )
236         {
237             tool.setIndentation( StringEscapeUtils.unescapeJava(
238                 commandLine.getOptionValue( Options.INDENTATION_STRING_OPTION.getOpt() ) ) );
239 
240         }
241         if ( commandLine.hasOption( Options.LINE_SEPARATOR_OPTION.getOpt() ) )
242         {
243             tool.setLineSeparator( StringEscapeUtils.unescapeJava(
244                 commandLine.getOptionValue( Options.LINE_SEPARATOR_OPTION.getOpt() ) ) );
245 
246         }
247 
248         return tool;
249     }
250 
251     /**
252      * Gets the specification to process from a given model.
253      *
254      * @param commandLine The command line specifying the specification to process.
255      * @param model The model to get the specification to process from.
256      *
257      * @return The specification to process or {@code null}.
258      *
259      * @throws NullPointerException if {@code commandLine} or {@code model} is {@code null}.
260      */
261     protected final Specification getSpecification( final CommandLine commandLine, final Model model )
262     {
263         if ( commandLine == null )
264         {
265             throw new NullPointerException( "commandLine" );
266         }
267         if ( model == null )
268         {
269             throw new NullPointerException( "model" );
270         }
271 
272         Specification s = null;
273 
274         if ( commandLine.hasOption( Options.SPECIFICATION_OPTION.getOpt() ) )
275         {
276             final String identifier = commandLine.getOptionValue( Options.SPECIFICATION_OPTION.getOpt() );
277             final Modules modules = ModelHelper.getModules( model );
278 
279             if ( modules != null )
280             {
281                 s = modules.getSpecification( identifier );
282             }
283 
284             if ( s == null )
285             {
286                 this.log( Level.WARNING, Messages.getMessage( "specificationNotFoundWarning", identifier ), null );
287             }
288         }
289 
290         return s;
291     }
292 
293     /**
294      * Gets the implementation to process from a given model.
295      *
296      * @param commandLine The command line specifying the implementation to process.
297      * @param model The model to get the implementation to process from.
298      *
299      * @return The implementation to process or {@code null}.
300      *
301      * @throws NullPointerException if {@code commandLine} or {@code model} is {@code null}.
302      */
303     protected final Implementation getImplementation( final CommandLine commandLine, final Model model )
304     {
305         if ( commandLine == null )
306         {
307             throw new NullPointerException( "commandLine" );
308         }
309         if ( model == null )
310         {
311             throw new NullPointerException( "model" );
312         }
313 
314         Implementation i = null;
315 
316         if ( commandLine.hasOption( Options.IMPLEMENTATION_OPTION.getOpt() ) )
317         {
318             final String identifier = commandLine.getOptionValue( Options.IMPLEMENTATION_OPTION.getOpt() );
319             final Modules modules = ModelHelper.getModules( model );
320 
321             if ( modules != null )
322             {
323                 i = modules.getImplementation( identifier );
324             }
325 
326             if ( i == null )
327             {
328                 this.log( Level.WARNING, Messages.getMessage( "implementationNotFoundWarning", identifier ), null );
329             }
330         }
331 
332         return i;
333     }
334 
335     /**
336      * Gets the module to process from a given model.
337      *
338      * @param commandLine The command line specifying the implementation to process.
339      * @param model The model to get the module to process from.
340      *
341      * @return The module to process or {@code null}.
342      *
343      * @throws NullPointerException if {@code model} is {@code null}.
344      */
345     protected final Module getModule( final CommandLine commandLine, final Model model )
346     {
347         if ( commandLine == null )
348         {
349             throw new NullPointerException( "commandLine" );
350         }
351         if ( model == null )
352         {
353             throw new NullPointerException( "model" );
354         }
355 
356         Module m = null;
357 
358         if ( commandLine.hasOption( Options.MODULE_OPTION.getOpt() ) )
359         {
360             final String name = commandLine.getOptionValue( Options.MODULE_OPTION.getOpt() );
361             final Modules modules = ModelHelper.getModules( model );
362 
363             if ( modules != null )
364             {
365                 m = modules.getModule( name );
366             }
367 
368             if ( m == null )
369             {
370                 this.log( Level.WARNING, Messages.getMessage( "moduleNotFoundWarning", name ), null );
371             }
372         }
373 
374         return m;
375     }
376 
377     /**
378      * Gets a flag indicating that all modules are requested to be processed.
379      *
380      * @param commandLine The command line to process.
381      *
382      * @return {@code true}, if processing of all modules is requested; {@code false}, else.
383      *
384      * @throws NullPointerException if {@code commandLine} is {@code null}.
385      *
386      * @see #getSpecification(org.apache.commons.cli.CommandLine, org.jomc.modlet.Model)
387      * @see #getImplementation(org.apache.commons.cli.CommandLine, org.jomc.modlet.Model)
388      * @see #getModule(org.apache.commons.cli.CommandLine, org.jomc.modlet.Model)
389      */
390     protected final boolean isModulesProcessingRequested( final CommandLine commandLine )
391     {
392         if ( commandLine == null )
393         {
394             throw new NullPointerException( "commandLine" );
395         }
396 
397         return !( commandLine.hasOption( Options.SPECIFICATION_OPTION.getOpt() )
398                   || commandLine.hasOption( Options.IMPLEMENTATION_OPTION.getOpt() )
399                   || commandLine.hasOption( Options.MODULE_OPTION.getOpt() ) );
400 
401     }
402 
403     /**
404      * Gets a locale from a command line.
405      *
406      * @param commandLine The command line to get a locale from.
407      *
408      * @return The locale from {@code commandLine} or {@code null}, if {@code commandLine} does not hold options
409      * specifying a locale.
410      */
411     protected final Locale getLocale( final CommandLine commandLine )
412     {
413         if ( commandLine == null )
414         {
415             throw new NullPointerException( "commandLine" );
416         }
417 
418         Locale locale = null;
419 
420         final String lc = commandLine.hasOption( Options.LANGUAGE_OPTION.getOpt() )
421                               ? commandLine.getOptionValue( Options.LANGUAGE_OPTION.getOpt() )
422                               : null;
423 
424         final String cc = commandLine.hasOption( Options.COUNTRY_OPTION.getOpt() )
425                               ? commandLine.getOptionValue( Options.COUNTRY_OPTION.getOpt() )
426                               : null;
427 
428         final String lv = commandLine.hasOption( Options.LOCALE_VARIANT_OPTION.getOpt() )
429                               ? commandLine.getOptionValue( Options.LOCALE_VARIANT_OPTION.getOpt() )
430                               : null;
431 
432         if ( lc != null || cc != null || lv != null )
433         {
434             locale = new Locale( StringUtils.defaultString( lc ),
435                                  StringUtils.defaultString( cc ),
436                                  StringUtils.defaultString( lv ) );
437 
438         }
439 
440         return locale;
441     }
442 
443 }