View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.cpd;
    5
    6   import java.util.Properties;
    7
    8   public class LanguageFactory {
    9
    10     public static String[] supportedLanguages = new String[]{"java", "jsp", "cpp", "c", "php", "ruby","fortran" };
    11     private static final String SUFFIX = "Language";
    12     public static final String EXTENSION = "extension";
    13     public static final String BY_EXTENSION = "by_extension";
    14     private static final String PACKAGE = "net.sourceforge.pmd.cpd.";
    15
    16      public Language createLanguage(String language) {
    17          return createLanguage(language, new Properties());
    18      }
    19
    20     public Language createLanguage(String language, Properties properties)
    21     {
    22       language = this.languageAliases(language);
    23       // First, we look for a parser following this syntax 'RubyLanguage'
    24       Language implementation;
    25       try {
    26         implementation = this.dynamicLanguageImplementationLoad(this.languageConventionSyntax(language));
    27         if ( implementation == null )
    28         {
    29           // if it failed, we look for a parser following this syntax 'CPPLanguage'
    30           implementation = this.dynamicLanguageImplementationLoad(language.toUpperCase());
    31           //TODO: Should we try to break the coupling with PACKAGE by try to load the class
    32           // based on her sole name ?
    33           if ( implementation == null )
    34           {
    35             // No proper implementation
    36             // FIXME: We should log a warning, shouldn't we ?
    37             return new AnyLanguage(language);
    38           }
    39         }
    40         return implementation;
    41       } catch (InstantiationException e) {
    42         e.printStackTrace();
    43       } catch (IllegalAccessException e) {
    44         e.printStackTrace();
    45       }
    46       return null;
    47     }
    48
    49       private String languageAliases(String language)
    50       {
    51         // CPD and C language share the same parser
    52         if ( "c".equals(language) )
    53           return "cpp";
    54         return language;
    55       }
    56
    57      private Language dynamicLanguageImplementationLoad(String language) throws InstantiationException, IllegalAccessException
    58      {
    59          try {
    60              return (Language) this.getClass().getClassLoader().loadClass(
    61                  PACKAGE + language + SUFFIX).newInstance();
    62          } catch (ClassNotFoundException e) {
    63              // No class found, returning default implementation
    64              // FIXME: There should be somekind of log of this
    65              return null;
    66          } catch (NoClassDefFoundError e) {
    67              // Windows is case insensitive, so it may find the file, even though
    68              // the name has a different case. Since Java is case sensitive, it
    69              // will not accept the classname inside the file that was found and
    70              // will throw a NoClassDefFoundError
    71              return null;
    72          }
    73      }
    74
    75     /*
    76      * This method does simply this:
    77      * ruby -> Ruby
    78      * fortran -> Fortran
    79      * ...
    80      */
    81     private String languageConventionSyntax(String language) {
    82         return (language.charAt(0) + "").toUpperCase() + language.substring(1, language.length()).toLowerCase();
    83      }
    84  }